Saving Beans
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4941 Accepted Submission(s): 1957
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.
1 2 5
2 1 5
3
Hint
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.
题目大意:
由n个不同的盒子,在每个盒子中放一些求(可以不放),使得总球数小雨等于m,求方案数(mod p).
1<=n,m<=10^9,1<p<10^5,保证p是素数
分析:
设最后放了k个球,根据"隔板法"由方案数C(k+n-1,n-1),:
ans=C(n-1,n-1)+C(n,n-1)+C(n+1,n-1)+……+C(n+m-2,n-1)+C(n+m-1,n-1)
=C(n+m,n);(mod p)
由于数据范围很大,C(n,m)=C(n-1,m)+C(n-1,m-1);显然会TLE
最后组合数还要mod p,这时候 Lucas定理 闪亮登场
============================================
Lucas定理(shenben简单总结版)
============================================
Lucas定理1:
Lucas(n,m,p)=cm(n%p,m%p)*Lucas(n/p,m/p,p);{其中cm(a,b)=C(a,b)%p;Lucas(x,0,p)=1;}
Lucas定理2:
把n写成p进制a[n]a[n-1]……a[0];
把m写成p进制b[n]b[n-1]……b[0];(不够位数的话,显然前面是 0)
则:C(a[n],b[n])*C(a[n-1],b[n-1])*……*C(a[0],b[0])
=C(n,m) (mod p);
ps:Lucas最大的数据处理能力是p在10^5左右。
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
const int N=1e5+;
ll n,m,p,a[N]={};
ll fpow(ll a,ll b){
ll res=;
for(;b;b>>=,a=a*a%p) if(b&) res=res*a%p;
return res;
}
ll C(ll n,ll m){
if(m>n) return ;
return a[n]*fpow(a[m],p-)%p*fpow(a[n-m],p-)%p;
}
ll lucas(ll n,ll m){
if(!m) return ;
return C(n%p,m%p)*lucas(n/p,m/p)%p;
}
int main(){
int T;cin>>T;
while(T--){
cin>>n>>m>>p;
for(int i=;i<=p;i++) a[i]=a[i-]*i%p;
cout<<lucas(n+m,n)<<'\n';
}
return ;
}