题目:http://acm.hdu.edu.cn/showproblem.php?pid=3037
题意:
把不超过m颗豆子放到n稞树上,问总共有多少种方法?对p取模。
分析:
利用插板法可得把m个豆子放到n棵树上种类数为
Cn−1n+m−1
所以
ans=Cn−1n+m−1+Cn−2n+m−2+...C0m
根据组合数公式
ans=Cnn+m
因为n和m的范围很大,P较小,所以用Lucas定理+逆元求组合数
代码:
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>
using namespace std;
typedef long long ll;
const int mod=1e4+7;
const int N=1e5+9;
ll fac[N];
ll qmod(ll a,ll b,ll p)
{
ll ans=1;
for(;b;b>>=1){
if(b&1)ans=ans*a%p;
a=a*a%p;
}
return ans;
}
void init(int p)
{
fac[0]=1;
for(int i=1;i<=p;i++)
fac[i]=fac[i-1]*i%p;
}
ll Lucas(ll n,ll m,ll p)
{
ll ans=1;
while(n&&m){
ll a=n%p,b=m%p;
if(a<b)return 0;
ans=ans*fac[a]*qmod(fac[b]*fac[a-b]%p,p-2,p)%p;
n/=p;
m/=p;
}
return ans;
}
int n,m,p;
int main()
{
int T;scanf("%d",&T);
while(T--){
cin>>n>>m>>p;
init(p);
cout<<Lucas(n+m,m,p)<<endl;
}
}