标签:
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=5446
思路:Lucas求出所有a[i]=C(n,m)%m[i],中国剩余定理求出最终结果x (LL*LL会爆掉,手写乘法)。
中国剩余定理:
设m1,m2,....mn是两两互质的正整数,对任意给定的整数a1,a2,....an必存在整数,满足
x≡a1 (mod m1),x≡a2 (mod m2),x≡a3 (mod m3)......
并且满足上列方程组的解x(mod m1m2m3.....mn)是存在唯一的。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long LL; int k; LL n,m; LL p[15],a[15]; LL fac[100005]; LL qmul(LL x,LL y,LL mod) { x=(x%mod+mod)%mod; y=(y%mod+mod)%mod; LL ret=0; while(y) { if(y&1) ret=(ret+x)%mod; x=x*2%mod; y>>=1; } return ret; } LL extgcd(LL a,LL b,LL& x,LL& y) { LL d,t; if(!b) { x=1; y=0; return a; } d=extgcd(b,a%b,x,y); t=x; x=y; y=t-a/b*y; return d; } LL CRT() { LL M=1,ans=0,x,y; for(int i=1; i<=k; i++) M*=p[i]; for(int i=1; i<=k; i++) { LL mi=M/p[i]; extgcd(mi,p[i],x,y); ans=(ans+qmul(qmul(mi,x,M),a[i],M))%M; } if(ans<0) ans=ans+M; return ans; } LL PowMod(LL a,LL b,LL mod) { LL ret=1; while(b) { if(b&1) ret=(ret*a)%mod; a=(a*a)%mod; b>>=1; } return ret; } void Get_Fac(LL mod) { fac[0]=1; for(int i=1;i<=mod;i++) fac[i]=(fac[i-1]*i)%mod; } LL Lucas(LL n,LL m,LL p) { LL ret=1; while(n&&m) { LL a=n%p,b=m%p; if(a<b) return 0; ret=(ret*fac[a]*PowMod(fac[b]*fac[a-b]%p,p-2,p))%p; n/=p,m/=p; } return ret; } int main() { int t; ios::sync_with_stdio(0); cin>>t; while(t--) { cin>>n>>m>>k; memset(a,0,sizeof(a)); for(int i=1; i<=k; i++) { cin>>p[i]; Get_Fac(p[i]); a[i]=Lucas(n,m,p[i]); } cout<<CRT()<<endl; } return 0; }
Hdu 5446 Unknown Treasure(Lucas+中国剩余定理)
标签:
原文地址:http://blog.csdn.net/wang2147483647/article/details/52122439