题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1133
思路:有m个人拿50元的纸币,n个人拿100元的纸币门票价格是50元,要求每个售票员遇到100元时都能找回顾客50元。
(1)如果m
(2)m>=n,总共有C(m+n,n)种可能,只要求出不符合要求的即可。
假如有一个m=3,n=2的序列01100,它不合法,将第二个1后的0变为1,1变为0,得到01111,显然它也不合法。
由此可以看出每一个(m,n)序列都能由(m-1,n+1)序列推过来,所以不合法的序列数总共有C(m+n,m+1)个
,总共合法的序列有C(m+n,n)- C(m+n,m+1)= (m+n)!*(m-n+1)/(m+1)个。
#include
#include
#include
using namespace std;
const int base = 10000;
const int maxn = 100;
int f[maxn*2][maxn*2],n,m,ans[maxn+20];
void mul(int a[],int x)
{
int i,tmp=0;
for(i=maxn-1;i>=0;i--)
{
tmp+=a[i]*x;
a[i]=tmp%base;
tmp/=base;
}
}
void chu(int a[],int x)
{
int i,tmp=0;
for(i=0;i<=maxn;i++)
{
tmp=tmp*base+a[i];
a[i]=tmp/x;
tmp%=x;
}
}
void Init()
{
f[0][maxn-1]=f[1][maxn-1]=1;
for(int i=2;i<=200;i++)
{
memcpy(f[i],f[i-1],maxn*sizeof(int));
mul(f[i],i);
}
}
int main(void)
{
int i,j,pt=1;
Init();
while(~scanf("%d%d",&m,&n)&&(n+m))
{
printf("Test #%d:\n",pt++);
if(n>m)
{
printf("0\n");
continue;
}
memcpy(ans,f[n+m],maxn*sizeof(int));
mul(ans,m-n+1);
chu(ans,m+1);
i=0;
while(ans[i]==0) i++;
printf("%d",ans[i++]);
while(i"%04d",ans[i++]);
printf("\n");
}
return 0;
}