标签:
题意 : 给了n课不同的树,要求将 0,1,2,3,4,5,...m个松果,分别放在n棵树上的方案数有多少,
我们这样考虑, 如果将m个相同的松果 放入n棵树中 , 转化一下,我们让每个点至少放1个松果,
将 摆成 一行 n+m 个 ,然后 n+m 中间会有n+m-1个空格 加末尾一个就说明有 n+m个 位置可以插入 东西
假设 第一个被插入的间隔是i表示 1-i之间全部是第一棵树的存放数量,,以此类推,当最后一个插入的间隔没有放在最末尾的时候,表明并没有 那么m个松果可以放的,这样我们求C(n+m,n)就可以了 C(n+m,p)用lucas 计算
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <string.h> 5 using namespace std; 6 const int maxn =100005; 7 typedef long long LL; 8 LL fax[maxn]; 9 void getfax(int p) 10 { 11 fax[0]=1; 12 for(LL i=1; i<=p; i++) 13 { 14 fax[i]=(fax[i-1]*i)%p; 15 } 16 } 17 void gcd(LL a, LL b, LL &d, LL &x, LL &y){ 18 if(!b){ 19 d=a; x=1; y=0; 20 }else{ 21 gcd(b,a%b,d,y,x); y-=x*(a/b); 22 } 23 } 24 LL inv(LL a, LL n) 25 { 26 LL d,x,y; 27 gcd(a,n,d,x,y); 28 return (x+n)%n; 29 } 30 LL lucas(int n, int m, int p) 31 { 32 LL ans=1; 33 while(n&&m) 34 { 35 int a=n%p,b=m%p; 36 if(a<b)return 0; 37 ans=( ( (ans*fax[a])%p ) * ( inv(fax[b]*fax[a-b] , p)))%p; 38 n/=p; 39 m/=p; 40 } 41 return ans; 42 } 43 int main() 44 { 45 int n,m,p; 46 int cas; 47 scanf("%d",&cas); 48 for(int cc=1; cc<=cas; cc++) 49 { 50 scanf("%d%d%d",&n,&m,&p); 51 getfax(p); 52 printf("%I64d\n",lucas(n+m,n,p)); 53 } 54 55 return 0; 56 }
标签:
原文地址:http://www.cnblogs.com/Opaser/p/4793983.html