Unknown Treasure
Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 2461 Accepted Submission(s): 905
Problem Description
On the way to the next secret treasure hiding place, the mathematician discovered a cave unknown to the map. The mathematician entered the cave because it is there. Somewhere deep in the cave, she found a treasure chest with a combination lock and some numbers on it. After quite a research, the mathematician found out that the correct combination to the lock would be obtained by calculating how many ways are there to pick
m
different apples among
n
of them and modulo it with
M
.
M
is the product of several different primes.
Input
On the first line there is an integer
T(T≤20)
representing the number of test cases.
Each test case starts with three integers n,m,k(1≤m≤n≤10
18
,1≤k≤10)
on a line where
k
is the number of primes. Following on the next line are
k
different primes
p
1
,...,p
k![]()
. It is guaranteed that
M=p
1
⋅p
2
⋅⋅⋅p
k
≤10
18![]()
and
p
i
≤10
5![]()
for every
i∈{1,...,k}
.
Each test case starts with three integers n,m,k(1≤m≤n≤10
Output
For each test case output the correct combination on a line.
Sample Input
1 9 5 2 3 5
Sample Output
6
Source
Recommend
题解:Lucas定理+中国剩余定理
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 20
#define LL long long
#define pa pair<LL,LL>
using namespace std;
LL n,m,k,p[N],a[N],mod,jc[20][200003];
LL init()
{
for (int i=1;i<=k;i++) {
jc[i][0]=jc[i][1]=1;
for (int j=2;j<=p[i];j++)
jc[i][j]=jc[i][j-1]*j%p[i];
}
}
LL mul(LL a,LL b,LL mod)
{
LL res=0;
while (b) {
if (b&1) res=(res+a)%mod;
a=(a+a)%mod;
b>>=1;
}
return res;
}
LL quickpow(LL num,LL x,LL p)
{
LL base=num%p; LL ans=1;
while (x) {
if (x&1) ans=(ans*base)%p;
x>>=1;
base=(base*base)%p;
}
return ans;
}
void exgcd(LL a,LL b,LL &x,LL &y)
{
if (b==0) {
x=1; y=0; return;
}
exgcd(b,a%b,x,y);
LL t=y;
y=x-(a/b)*y;
x=t;
}
LL inverse(LL a,LL b)
{
LL x,y;
exgcd(a,b,x,y);
return (x%b+b)%b;
}
/*pa solve(int k,LL n)
{
if (n==0) return make_pair(0,1);
LL x=n/p[k],y=n/p[k];
LL ans=1;
if (y) {
for (LL i=2;i<p[k];i++) {
if (i%p[k]!=0) ans=(ans*(LL)i)%p[k];
}
ans=quickpow(ans,y,p[k]);
}
for (LL i=y*p[k]+1;i<=n;i++)
if (i%p[k]!=0) ans=(ans*(LL)i)%p[k];
pa t=solve(k,x);
return make_pair(t.first+x,ans*t.second%p[k]);
}*/
/*LL calc(int k,LL n,LL m)
{
if (n<m) return 0;
pa a=solve(k,n),b=solve(k,m),c=solve(k,n-m);
LL t1=quickpow(p[k],a.first-b.first-c.first,p[k])*a.second%p[k];
LL t2=inverse(b.second,p[k])%p[k];
LL t3=inverse(c.second,p[k])%p[k];
return t1*t2*t3%p[k];
}*/
LL calc(int i,LL n,LL m)
{
if (m>n) return 0;
return jc[i][n]*quickpow(jc[i][m]*jc[i][n-m]%p[i],p[i]-2,p[i])%p[i];
}
LL lucas(int i,LL n,LL m)
{
if (m==0) return 1;
return calc(i,n%p[i],m%p[i])*lucas(i,n/p[i],m/p[i])%p[i];
}
LL china()
{
LL x,y,ans=0;
for (int i=1;i<=k;i++){
LL r=mod/p[i];
//exgcd(r,p[i]);
ans=(ans+mul(mul(r,inverse(r,p[i]),mod),a[i],mod))%mod;
}
return ans;
}
int main()
{
freopen("a.in","r",stdin);
freopen("my.out","w",stdout);
int T;
scanf("%d",&T);
while (T--) {
cin>>n>>m>>k; mod=1;
for (int i=1;i<=k;i++)
scanf("%I64d",&p[i]),mod*=p[i];
init();
for (int i=1;i<=k;i++)
a[i]=lucas(i,n,m);
//for (int i=1;i<=k;i++) cout<<a[i]<<" ";
// cout<<endl;
printf("%I64d\n",china());
}
}