hdu 5446(2015长春网络赛J题 Lucas定理+中国剩余定理)
题意:M=p1*p2*...pk;求C(n,m)%M,pi小于10^5,n,m,M都是小于10^18。 pi为质数
M不一定是质数 所以只能用Lucas定理求k次 C(n,m)%Pi
最后会得到一个同余方程组
x≡B[0](mod p[0])
x≡B[1](mod p[1])
x≡B[2](mod p[2])
......
解这个同余方程组 用中国剩余定理
Sample Input
1
9 5 2
3 5
Sample Output
6
1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 # include <string> 6 # include <cmath> 7 # include <queue> 8 # include <list> 9 # define LL long long 10 using namespace std ; 11 12 LL n , m , k ; 13 LL p[15] , B[15] ; 14 15 LL Ext_gcd(LL a,LL b,LL &x,LL &y){ //扩展欧几里德算 16 if(a==0&&b==0) return -1; 17 if(b==0) { x=1, y=0; return a; } 18 LL d= Ext_gcd(b,a%b,y,x); 19 y-= a/b*x; 20 return d; 21 } 22 //ax = 1(mod m) 23 LL Inv(LL a,LL m){ //求逆元 a对m的逆元 24 LL d,x,y,t = m; 25 d= Ext_gcd(a,t,x,y); 26 if(d==1) return (x%t+t)%t; 27 return -1; 28 } 29 30 LL Cm(LL n, LL m, LL p) //求组合数 31 { 32 LL a=1, b=1; 33 if(m>n) return 0; 34 while(m) 35 { 36 a=(a*n)%p; 37 b=(b*m)%p; 38 m--; 39 n--; 40 } 41 return (LL)a*Inv(b,p)%p; //(a/b)%p 等价于 a*(b,p)的逆元 42 } 43 44 int Lucas(LL n, LL m, LL p) //把n分段递归求解相乘 45 { 46 if(m==0) return 1; 47 return (LL)Cm(n%p,m%p,p)*(LL)Lucas(n/p,m/p,p)%p; 48 } 49 50 LL multi(LL a,LL b,LL p) //大数 (a×b)%p 51 { 52 LL ret=0; 53 while(b) 54 { 55 if(b&1) 56 ret=(ret+a)%p; 57 a=(a+a)%p; 58 b>>=1; 59 } 60 return ret; 61 62 } 63 64 LL china(LL n,LL *m, LL *a)// x ≡ a(mod m) 65 { 66 LL M=1,d,y,x=0; 67 int i ; 68 for (i = 0 ; i < n ; i++) 69 M*=m[i]; 70 for (i = 0 ; i < n ; i++) 71 { 72 LL w=M/m[i]; 73 d=Ext_gcd(m[i],w,d,y); 74 x=(x+multi(multi(y,w,M), a[i], M))%M; 75 } 76 return (x+M)%M; 77 } 78 79 int main() 80 { 81 //freopen("in.txt","r",stdin) ; 82 int T ; 83 cin>>T ; 84 while(T--) 85 { 86 cin>>n>>m>>k ; 87 int i ; 88 for (i = 0 ; i < k ; i++) 89 { 90 cin>>p[i] ; 91 B[i] = Lucas(n , m , p[i]) ; 92 } 93 cout<<china(k , p , B)<<endl ; 94 } 95 return 0; 96 }