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 }
View Code

 

posted @ 2015-09-21 19:48  __Meng  阅读(164)  评论(0编辑  收藏  举报