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.
数论Lucas定理是用来求 c(n,m) mod p的值,p是素数(从n取m组合,模上p)。
描述为:
Lucas(n,m,p)=cm(n%p,m%p)* Lucas(n/p,m/p,p)
Lucas(x,0,p)=1;
而
cm(a,b)=a! * (b!*(a-b)!)^(p-2) mod p
也= (a!/(a-b)!) * (b!)^(p-2)) mod p
这里,其实就是直接求 (a!/(a-b)!) / (b!) mod p
由于 (a/b) mod p = a * b^(p-2) mod p
然后 插板法求排列组合
题意中说不超过m个豆。
可以考虑m个的情况 并且可以有空 可以不放 所以可以考虑加上一棵树放不放的就变成 n+1 棵树。
等效为求:
x1+x2+......+xn+1=m 的非负整数解个数。
因为非负的比较难求,所以我们可以转化成整数解。X1=X1+1,X2=X2+1......Xn=Xn+n;
即 X1+X2+.......+Xn+1=n+1+m
等效考虑就是:将n+1+m个球用n个隔板分成n+1份,这时一共有n+1+m-1=n+m个空
所以结果就是C(n,n+m)=C(m,n+m)
AC代码
#include <iostream> #include <stdio.h> #include <string.h> #include <math.h> #include <algorithm> using namespace std; typedef long long LL; LL f[100100]; void init(LL p) { f[0]=1; for(int i=1;i<=p;i++) f[i]=f[i-1]*i%p; } long long mod_pow(LL x,LL n,LL p) { LL res=1; while(n){ if(n&1)res=res*x%p; x=x*x%p; n>>=1; } return res; } long long lucas(LL n,LL m,LL p) { LL res=1; while(n&&m){ int x=n%p; int y=m%p; if(x<y) return 0; if(y>x-y)y=x-y; //C(n,n+m)=c(m,n+m),选取较小值可以减少循环次数 res=res*f[x]*mod_pow(f[y]*f[x-y]%p,p-2,p)%p; n/=p;m/=p; } return res; } int main() { int t; scanf("%d",&t); while(t--) { LL n,m,p; scanf("%lld%lld%lld",&n,&m,&p); init(p); printf("%lld\n",lucas(n+m,m,p)); } return 0; }