数学:拓展Lucas定理
拓展Lucas定理解决大组合数取模并且模数为任意数的情况
大概的思路是把模数用唯一分解定理拆开之后然后去做
然后要解决的一个子问题是求模质数的k次方
将分母部分转化成逆元再去做就好了
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn = 100000 + 10; 4 typedef long long LL; 5 6 LL Pow(LL n, LL m, LL mod) { 7 LL ans = 1; 8 while(m > 0) { 9 if(m & 1) ans = (LL)ans * n % mod; 10 n = (LL)n * n % mod; m >>= 1; 11 } 12 return ans; 13 } 14 LL Pow(LL n,LL m) { 15 LL ans = 1; 16 while(m > 0) { 17 if(m & 1) ans = ans * n; 18 n = n * n; m >>= 1; 19 } 20 return ans; 21 } 22 LL x, y; 23 LL exgcd(LL a, LL b) { 24 if(a == 0) { 25 x = 0, y = 1; 26 return b; 27 }LL r = exgcd(b%a, a); 28 LL t = x; x = y - (b/a)*x; y = t; 29 return r; 30 } 31 LL rev(LL a, LL b) { exgcd(a, b); return ((x % b) + b) % b; } 32 LL Calc(LL n, LL p, LL t) { 33 if(n == 0) return 1; 34 35 LL s = Pow(p, t), k = n / s, tmp = 1; 36 for(LL i=1; i<=s; i++) if(i % p) tmp = (LL)tmp * i % s; 37 38 LL ans = Pow(tmp, k, s); 39 for(LL i=s*k + 1; i<=n; i++) if(i % p) ans = (LL)ans * i % s; 40 41 return (LL)ans * Calc(n / p, p, t) % s; 42 } 43 LL C(LL n, LL m, LL p, LL t) { 44 LL s = Pow(p, t), q = 0; 45 for(LL i=n; i; i/=p) q += i / p; 46 for(LL i=m; i; i/=p) q -= i / p; 47 for(LL i=n-m; i; i/=p) q -= i / p; 48 49 LL ans = Pow(p, q); 50 LL a = Calc(n, p, t), b = Calc(m, p, t), c = Calc(n-m, p, t); 51 return (LL)(ans * a * rev(b, s) * rev(c, s)) % s; 52 } 53 LL China(LL A[], LL M[], LL cnt) { 54 LL ans = 0, m, n = 1; 55 for(LL i=1; i<=cnt; i++) n *= M[i]; 56 for(LL i=1; i<=cnt; i++) { 57 m = n / M[i]; 58 exgcd(M[i], m); 59 ans = (ans + (LL)y * m * A[i]) % n; 60 } 61 return (ans + n) % n; 62 } 63 LL A[maxn], M[maxn], cnt; 64 LL Lucas(LL n, LL m, LL mod) { 65 for(LL i=2; i*i <= mod; i++) if(mod % i == 0) { 66 LL t = 0; 67 while(mod % i == 0) t++, mod /= i; 68 M[++cnt] = Pow(i, t); 69 A[cnt] = C(n, m, i, t); 70 }if(mod > 1) { 71 M[++cnt] = mod; 72 A[cnt] = C(n, m, mod, 1); 73 } 74 return China(A, M, cnt); 75 } 76 LL n, k, p; 77 int main() { 78 cin >> n >> k >> p; 79 cout << Lucas(n, k, p) << endl; 80 return 0; 81 }
然后补充一个内容,线性时间复杂度内求出所有的逆元
A[i] = -(p / i) * A[p % i];