Saving Beans
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5952 Accepted Submission(s): 2379
Now they turn to you for help, you should give them the answer. The result may be extremely huge; you should output the result modulo p, because squirrels can’t recognize large numbers.
Then followed T lines, each line contains three integers n, m, p, means that squirrels will save no more than m same beans in n different trees, 1 <= n, m <= 1000000000, 1 < p < 100000 and p is guaranteed to be a prime.
2 1 2 5 2 1 5
3 3HintHint For sample 1, squirrels will put no more than 2 beans in one tree. Since trees are different, we can label them as 1, 2 … and so on. The 3 ways are: put no beans, put 1 bean in tree 1 and put 2 beans in tree 1. For sample 2, the 3 ways are: put no beans, put 1 bean in tree 1 and put 1 bean in tree 2.
题意:
将不超过m个豆子放在n棵不同的树上,一共有多少种方法
题解:
可以将本题转化为n个数的和小于等于m的方案书有多少
如果和恰好等于m,那么就等价于方程x1+x2+...+xn = m的解的个数
此时和多重集合的组合数一样的解法,组合数也一样,附上两张上课讲课的内容截图
现在需要求不大于m的和
即此时 i = 0,1,2,3,4,,,,m,同上面解法一样
求x1+x2+...+xn = i 的解的个数,把所有的这样的 i 方程的解求和即为答案
根据公式C(n,k) = C(n-1,k)+C(n-1,k-1)得
C(n-1,0)+C(n,1)+...+C(n+m-1,m)
= C(n,0)+C(n,1)+C(n+1,2)+...+C(n+m-1,m)
= C(n+m,m)
看不懂的可以反着化回去
下面介绍Lucas定理:
Lucas定理是用来求 C(n,m) mod p的值,p是素数(从n取m组合,模上p)
Lucas最大的数据处理能力是p在10^5左右
描述为:
Lucas(n,m,p)=C(n%p,m%p)* Lucas(n/p,m/p,p)
Lucas(x,0,p)=1;
A、B是非负整数,p是质数。AB写成p进制:A=a[n]a[n-1]...a[0],B=b[n]b[n-1]...b[0]。
则组合数C(A,B)与C(a[n],b[n])*C(a[n-1],b[n-1])*...*C(a[0],b[0]) modp同余
即:Lucas(n,m,p)=c(n%p,m%p)*Lucas(n/p,m/p,p)
#include<stdio.h>
#define MAXN 1000010
typedef long long LL;
LL n,m,p;
LL powmod(LL a,LL b,LL MOD)
{
LL ans=1;
while(b){
if(b%2)
ans=ans*a%MOD;a=a*a%MOD;b/=2;
}
return ans;}
LL f[MAXN];
void init(LL p)
{
f[0]=1;
for(int i=1;i<=p;i++)
f[i]=(f[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*f[a]*powmod(f[b]*f[a-b]%p,p-2,p))%p;
n/=p;m/=p;
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
scanf("%I64d%I64d%I64d",&n,&m,&p);
init(p);
LL ans=lucas(n+m,m,p);
printf("%I64d\n",ans);
}
return 0;
}