题意:
求C(n,m)%(p1*p2*......pk),其中,p1*p2*......pk都是素数。
思路:
不会。。。数论是渣,赛后知道是Lucas定理+中国剩余定理。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100005;
long long fac[maxn],inv[maxn];
long long pow_mod(long long a,int n,int mod)
{
long long ret=1;
while(n)
{
if(n&1)
ret=ret*a%mod;
a=a*a%mod;
n>>=1;
}
return ret;
}
void init(int n)
{
fac[0]=1;
for(int i=1; i<n; i++)
fac[i]=fac[i-1]*i%n;
inv[n-1]=pow_mod(fac[n-1],n-2,n);
for(int i=n - 2; i>=0; i--)
inv[i]=inv[i+1]*(i+1)%n;
}
long long C (int n,int m,int mod)
{
if(m>n||m<0||n<0)
return 0;
return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
long long lucas(long long n,long long m,int mod)
{
if(m==0)
return 1;
return lucas(n/mod,m/mod,mod)*C(n%mod,m%mod,mod)%mod;
}
long long extend_gcd(long long a,long long b,long long & x,long long & y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
long long d=extend_gcd(b,a%b,y,x);
y-=x*(a/b);
return d;
}
long long mul(long long a,long long b,long long mod)
{
a=(a%mod+mod)%mod;
b=(b%mod+mod)%mod;
long long ret=0;
while(b)
{
if(b&1)
{
ret+=a;
if(ret>=mod)
ret-=mod;
}
b>>=1;
a<<=1;
if(a>=mod)
a-=mod;
}
return ret;
}
long long CRT(int n,long long *a,long long *m)
{
long long M=1,d,y,x=0;
for (int i=0; i<n; i++) M*=m[i];
for (int i=0; i<n; i++)
{
long long w=M/m[i];
extend_gcd(m[i],w,d,y);
x=(x+mul(mul(y,w,M),a[i],M));
}
return (x+M)%M;
}
int main ()
{
int t;
scanf("%d",&t);
while(t--)
{
long long n,m,k;
scanf("%lld%lld%lld",&n,&m,&k);
long long a[20],p[20];
for(int i=0; i<k; i++)
{
scanf("%lld",&p[i]);
init(p[i]);
a[i]=lucas(n,m,p[i]);
}
printf("%lld\n",CRT(k,a,p));
}
return 0;
}