题目:
题意:
把 m 个松果最多分到 n 颗树上,求有多少种分法
分析:
设第 i 颗树上放 Xi 个,无非等价于求解下式解的个数
由插板模型可得答案为:
而 1 =< k <= n,所以最终答案为:
如果 m < p 可直接求个逆元即可,若m > p,则m!和 p 一定不互质,这就不能求出逆元,这时有个叫卢卡斯的站了起来:
卢卡斯定理:
若 m/p 任然大于 p,递归求解就可
代码:
#include <iostream>
using namespace std;
typedef long long ll;
ll Pow(ll a,ll p)
{
ll ans = 1;
ll x = p-2;
while(x)
{
if(x&1) ans = ans*a%p;
a = a*a%p;
x>>=1;
}
return ans%p;
}
ll cal(ll n,ll m,ll p)
{
if(m>n) return 0;
ll res = 1;
for(int i=n;i>n-m;--i)
res = res*i%p;
ll a = 1;
for(int i=1;i<=m;++i)
a = a*i%p;
return res*Pow(a,p)%p;
}
ll Lucas(ll n,ll m,ll p)
{
if(m<p) return cal(n,m,p);
else return cal(n%p,m%p) * Lucas(n/p,m/p,p)%p;
}
int main()
{
ll t,n,m,p;
cin>>t;
while(t--)
{
cin>>n>>m>>p;
cout<<Lucas(n+m,m,p)<<endl;
}
return 0;
}