lucas定理 lucas(n,m,p)=C(n%p,m%p,p)*lucas(n/p,m/p,p),p是质数
证明:
n=ak*p^k+a(k-1)*p^(k-1)+........a0*p^0
m=bk*p^k+b(k-1)*p^(k-1)+........b0*p^0
(1+x)^p=1+x^p (mod p) p是质数 ,可以得到 (1+x)^(p^k)=1+x^(p^k) (mod p)
(1+x)^n=(1+x)^(ak*p^k)*(1+x)^(ak-1*p^(k-1))*........(1+x)^a0
=(1+x^(p^k))^ak*(1+x^(p^(k-1)))^ak-1*.........(1+x)^a0
C(n,m)x^m=C(ak,bk)*C(ak-1,bk-1)*.....C(a0,b0);
中国剩余定理:
a=a1 (mod n1)
a=a2 (mod n2)
.......
a=ak (mod nk)
M=n1*n2*n3*....nk
Mi=M/ni
Mi^(-1)是Mi在模ni下的逆元
n1,n2,n3...nk 是质数,a的一个解为 a= a1*M1*M1^(-1)+a2*M2*M2^(-1)+...........+ak*Mk*Mk^(-1)
证明 ai*Mi*Mi^(-1)%ni=ai j!=i aj*Mj*Mj^(-1)%ni=0 所以a%ni=ai;
这一题解法:
C(n,m)=ans[1] (mode n1)
C(n,m)=ans[2] (mode n2)
.....
C(n,m)=ans[k] (mode nk)
先用lucas求出ans[1..k],再用中国剩余定理求出C(n,m)
#include<bits/stdc++.h> using namespace std; #define rd(x) scanf("%d",&x) #define rdd(x,y) scanf("%d%d",&x,&y) #define rddd(x,y,z) scanf("%d%d%d",&x,&y,&z) #define rds(s) scanf("%s",s) #define rep(i,n) for(int i=0;i<n;i++) #define LL long long const int N = 1e3+10; const int inf=1e9; const int MOD=1e9+7; LL n,m; int p[15]; int k; void add(LL &a,LL b,LL md){ a+=b; a%=md; } LL mul(LL a,LL b,LL md){ LL ret=0; while(b){ if(b&1) add(ret,a,md); add(a,a,md); b>>=1; } return ret; } LL qmod(LL a,LL b,LL md){ LL ret=1; while(b){ if(b&1) ret=mul(ret,a,md); a=mul(a,a,md); b>>=1; } return ret; } LL C(LL n,LL m,LL md){ LL up=1,down=1; rep(i,m){ down=down*(i+1)%md; up=up*(n-i)%md; } return mul(up,qmod(down,md-2,md),md); } LL lucas(LL n,LL m,LL md){ if(n==0 || m==0) return 1; return mul(C(n%md,m%md,md),lucas(n/md,m/md,md),md); } LL M; LL ans[15]; int main() { #ifndef ONLINE_JUDGE freopen("aaa","r",stdin); #endif int T; rd(T); while(T--){ scanf("%I64d%I64d%d",&n,&m,&k); M=1; rep(i,k) scanf("%d",p+i+1); for(int i=1;i<=k;i++){ ans[i]=lucas(n,m,p[i]); M*=p[i]; } LL ret=0; for(int i=1;i<=k;i++){ LL Mi=M/p[i]; LL Mni=qmod(Mi,p[i]-2,p[i]); ret+=mul(mul(ans[i],Mi,M),Mni,M); ret%=M; } printf("%I64d\n",ret); } return 0; }