题目大意
输入n,m,k以及k个质数p1,p2,...,pk,求$C_n^m\%(p1*p2*...*pk)$。
思路
听群里大佬说了一句扩展Lucas,然后就去学(其实也可以中国剩余定理+Lucas)。
这里主要想说一下这题的数据,极容易爆long long。所以,
1.乘之前一定要%!
2.mod可能是1e18范围的,就要用快速乘!
代码
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 long long n,m,k,geshu[100005],prim[15],cn,M; 6 long long T; 7 8 long long qa(long long a,long long b,long long p) 9 { 10 long long ret=0; 11 while(b) 12 { 13 if(b&1) 14 { 15 ret+=a; 16 ret%=p; 17 } 18 a<<=1; 19 a%=p; 20 b>>=1; 21 } 22 return ret; 23 } 24 25 long long pw(long long a,long long b,long long p) 26 { 27 long long ret=1; 28 while(b) 29 { 30 if(b&1) 31 { 32 ret*=a;ret%=p; 33 } 34 a*=a;a%=p;b>>=1; 35 } 36 return ret%p; 37 } 38 39 long long exgcd(long long a,long long b,long long &x,long long &y) 40 { 41 if(b==0) 42 { 43 x=1;y=0; 44 return a; 45 } 46 long long xx,yy,ret=exgcd(b,a%b,xx,yy); 47 x=yy; 48 y=xx-a/b*yy; 49 return ret; 50 } 51 52 long long fac(long long n,long long p,long long pk) 53 { 54 if(n==0)return 1; 55 long long ret=1; 56 for(long long i=1;i<pk;i++) 57 { 58 if(i%p==0)continue; 59 else ret*=i,ret%=pk; 60 } 61 ret=pw(ret,n/pk,pk); 62 long long ls=pk*(n/pk)+1; 63 for(long long i=ls;i<=n;i++) 64 { 65 if(i%p!=0) 66 { 67 ret=(ret*(i%pk)%pk); 68 } 69 } 70 return ret*fac(n/p,p,pk)%pk; 71 } 72 73 long long comb(long long n,long long m,long long p,long long pk) 74 { 75 if(n<m)return 0; 76 if(n==m)return 1; 77 long long cnt=0; 78 long long facn=fac(n,p,pk); 79 long long facm=fac(m,p,pk); 80 long long facnm=fac(n-m,p,pk); 81 long long temx,temy,mni,nmni; 82 exgcd(facm,pk,temx,temy); 83 mni=(temx%pk+pk)%pk; 84 exgcd(facnm,pk,temx,temy); 85 nmni=(temx%pk+pk)%pk; 86 for(long long i=n;i;i/=p) 87 { 88 cnt+=i/p; 89 } 90 for(long long i=m;i;i/=p) 91 { 92 cnt-=i/p; 93 } 94 for(long long i=n-m;i;i/=p) 95 { 96 cnt-=i/p; 97 } 98 return ((pw(p,cnt,pk)*mni%pk)*nmni%pk)*facn%pk; 99 } 100 101 102 int main() 103 { 104 scanf("%lld",&T); 105 while(T--) 106 { 107 memset(geshu,0,sizeof(geshu)); 108 cn=0; 109 memset(prim,0,sizeof(prim)); 110 M=1; 111 scanf("%lld%lld%lld",&n,&m,&k); 112 for(long long i=1;i<=k;i++) 113 { 114 long long t; 115 scanf("%lld",&t); 116 if(!geshu[t]) 117 { 118 prim[++cn]=t; 119 geshu[t]++; 120 } 121 else geshu[t]++; 122 M*=t; 123 } 124 long long ans=0; 125 for(long long i=1;i<=cn;i++) 126 { 127 long long pk=1; 128 for(long long j=1;j<=geshu[prim[i]];j++)pk*=prim[i]; 129 long long ansi=comb(n,m,prim[i],pk); 130 long long mi=M/pk; 131 long long x,ti; 132 exgcd(mi,pk,ti,x); 133 ti=(ti%pk+pk)%pk; 134 ans+=qa(qa(ansi,mi,M),ti,M);ans%=M; 135 } 136 cout<<ans<<endl; 137 } 138 }