1. 问题描述:
给定 n 组询问,每组询问给定三个整数 a,b,p,其中 p 是质数,请你输出 Cba mod p 的值。
输入格式
第一行包含整数 n。接下来 n 行,每行包含一组 a,b,p。
输出格式
共 n 行,每行输出一个询问的解。
数据范围
1 ≤ n ≤ 20,
1 ≤ b ≤ a ≤ 10 ^ 18,
1 ≤ p ≤ 10 ^ 5,
输入样例:
3
5 3 7
3 1 5
6 4 13
输出样例:
3
3
2
来源:https://www.acwing.com/problem/content/description/889/
2. 思路分析:
这道题目由于a,b可能非常大,而p相对比较小(由于a可能非常大,所以a可能是p的倍数,a关于p的逆元可能不存在,所以不能够使用费马小定理来求解)此时就需要使用卢卡斯定理来求解对应的组合数,需要使用到下面这个公式进行求解,感觉卢卡斯定理的证明过程还是比较复杂的,时间复杂度为O(plognp)
3. 代码如下:
python(超时):
class Solution: # 快速幂 def quickPower(self, a: int, b: int, p: int): res = 1 while b > 0: if b & 1: res = res * a % p a = a * a % p b >>= 1 return res # 使用公式求解对应的组合数(阶乘的形式) def C(self, a: int, b: int, p: int): if a < b: return 0 up = down = 1 i, j = a, 1 while j <= b: up *= i down *= j i -= 1 j += 1 # 由费马小定理可知a ^ (p - 2)就是a关于p的逆元 return up * self.quickPower(down, p - 2, p) % p # p为取模数 def Lucas(self, a: int, b: int, p: int): if a < p and b < p: return self.C(a, b, p) return self.C(a % p, b % p, p) * self.Lucas(a // p, b // p, p) % p # 卢卡斯定理求解 def process(self): n = int(input()) for i in range(n): a, b, p = map(int, input().split()) print(self.Lucas(a, b, p)) if __name__ == "__main__": Solution().process()
c++:
#includeusing namespace std; typedef long long LL; LL quickPower(LL a, LL b, LL p){ LL res = 1 % p; while(b){ if(b & 1) res = res * a % p; a = a * a % p; b >>= 1; } return res; } LL C(LL a, LL b, LL p){ LL res = 1; for(int i = 1, j = a; i <= b;++i, --j){ res = res * j % p; res = res * quickPower(i, p - 2, p) % p; } return res % p; } LL lucas(LL a, LL b, LL p){ if(a < p && b < p) return C(a, b, p); return C(a % p, b % p, p) * lucas(a / p, b / p, p) % p; } int main(){ int n; cin >> n; while(n--){ LL a, b, p; cin >> a >> b >> p; cout << lucas(a, b, p) << endl; } return 0; }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)