您的位置:首页 > 其它

hdu3037 lucas

2015-09-09 10:54 211 查看
题意 : 给了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 计算

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string.h>
using namespace std;
const int maxn =100005;
typedef long long LL;
LL fax[maxn];
void getfax(int p)
{
fax[0]=1;
for(LL i=1; i<=p; i++)
{
fax[i]=(fax[i-1]*i)%p;
}
}
void gcd(LL a, LL b, LL &d, LL &x, LL &y){
if(!b){
d=a; x=1; y=0;
}else{
gcd(b,a%b,d,y,x); y-=x*(a/b);
}
}
LL inv(LL a, LL n)
{
LL d,x,y;
gcd(a,n,d,x,y);
return (x+n)%n;
}
LL lucas(int n, int m, int p)
{
LL ans=1;
while(n&&m)
{
int a=n%p,b=m%p;
if(a<b)return 0;
ans=( ( (ans*fax[a])%p  ) * (  inv(fax[b]*fax[a-b] , p)))%p;
n/=p;
m/=p;
}
return ans;
}
int main()
{
int n,m,p;
int cas;
scanf("%d",&cas);
for(int cc=1; cc<=cas; cc++)
{
scanf("%d%d%d",&n,&m,&p);
getfax(p);
printf("%I64d\n",lucas(n+m,n,p));
}

return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: