ACM-ICPC 2015 Changchun Preliminary Contest——J题

题目链接

题目大意

输入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 }

猜你喜欢

转载自www.cnblogs.com/LiqgNonqfu/p/11318881.html
今日推荐