分析:今天看到了lucas,学习了一下证明原理,找了个小例子应用了一下。题意是把不超过m个果子放在n个篮子里,有的篮子可以不放。假如有k个果子,问题可以转化为m-k个果子放在第n+1个篮子里,这样问题就转化成了把m个果子,放在n+1个篮子里。因为可以为0,我们每个篮子里,先放一个果子。这样就把问题转化成了把n+1+m个果子放到n+1个篮子里,每个篮子至少要选1个。然后就等于把果子排成一行是有n+m个缝隙,随意选n个缝隙把果子分成n+1组,所以结果就是 c(n,m+n)%p。然后就用到了lucas定理。
#include<cstdio>
typedef long long LL;
const int N = 100009;
LL fac[N];
void get_fac(int n){
fac[0] = 1;
for(int i = 1; i < n; i++){
fac[i] = fac[i-1] * i % n;
}
}
LL pow_mod(LL a, LL b, int mod){
int ret = 1;
while(b){
if(b&1) ret = ret * a % mod;
a = a * a % mod;
b >>= 1;
}
return ret;
}
LL inver(LL n, int p){
return pow_mod(n, p-2, p);
}
LL lucas(LL m, LL n, int mod){
int a,b;
LL ret = 1;
while(m && n){
a = m % mod; b = n % mod;
if(b < a) return 0;
ret = ret * fac[b] % mod * inver(fac[b-a] * fac[a] % mod, mod) % mod;
m /= mod; n /= mod;
}
return ret;
}
int main(){
int T;scanf("%d", &T);
while(T--){
int n,m,p,la = 0;
scanf("%d%d%d", &n, &m, &p);
get_fac(p);
printf("%I64d\n", lucas(m, n+m, p));
}
return 0;
}