题目地址: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;
}