思路1:
详解
当m<n时,明显不可能,输出0即可。
当m>=n时,对于一个不满足要求的m个50,n个100的序列,其对应着一个m+1个100,n-1个50的必然不成立的序列。
那么全部的可能序列的个数为:C [n+m] [m],而不符合要求的序列的个数为C[n+m][m+1],
所有答案为C[n+m][m]-C[n+m][ m+1]。
又因为 每个人都不同,所以要乘以m!*n!。
化简为(m+n)! *(m-n+1)/(m+1)。
(当m=n时,为卡特兰数)
思路2:
详解
用递推写,
#include <bits/stdc++.h>
using namespace std;
struct node
{
int num[100];//压位10000
node operator *(const int b)const
{
node res;
memset(res.num,0,sizeof(res.num));
for(int i=1;i<=num[0];i++)
res.num[i]=num[i]*b;
res.num[0]=num[0]+3;
for(int i=1;i<=res.num[0];i++)
{
res.num[i+1]+=res.num[i]/10000;
res.num[i]%=10000;
}
while(res.num[res.num[0]]==0)
res.num[0]--;
return res;
}
node operator /(const int b)const
{
node res;
memset(res.num,0,sizeof(res.num));
int t=0;
for(int i=num[0];i>=1;i--)
{
t=t*10000+num[i];
res.num[i]=t/b;
t%=b;
}
res.num[0]=num[0];
while(res.num[res.num[0]]==0)
res.num[0]--;
return res;
}
void print()
{
printf("%d",num[num[0]]);
for(int i=num[0]-1;i>=1;i--)
printf("%.4d",num[i]);
printf("\n");
}
};
node A[205];
void init()
{
A[0].num[0]=1;
A[0].num[1]=1;
A[1].num[0]=1;
A[1].num[1]=1;
for(int i=2;i<=200;i++)
A[i]=A[i-1]*i;
}
int main()
{
int n,m,cas=0;
init();
while(scanf("%d%d",&m,&n),n!=0||m!=0)
{
printf("Test #%d:\n",++cas);
if(m<n)
printf("0\n");
else
{
node ans=A[m+n]*(m-n+1)/(m+1);
ans.print();
}
}
return 0;
}
//也可以用递推式:ans[m][n]=ans[m-1][n]+ans[m][n-1];其中m>=n
//
一道类似的题:hdu1267
思路
#include <bits/stdc++.h>
using namespace std;
long long ans[25][25];
void init()
{
for(int i=0;i<=20;i++)
for(int j=0;j<=i;j++)
ans[i][j]=1;
for(int i=2;i<=20;i++)
{
for(int j=1;j<=i;j++)
ans[i][j]=ans[i-1][j]+ans[i][j-1];
}
}
int main()
{
int n,m;
init();
while(scanf("%d%d",&m,&n)!=EOF)
{
if(m<n)
printf("0\n");
else
printf("%lld\n",ans[m][n]);
}
return 0;
}
对应m个H,n个D的序列,其相对于在m个H,n-1个D的序列后面加上一个D,在m-1个H,n个D序列后面加上一个H。即ans[m][n]=ans[m-1][n]+ans[m][n-1]。
用笔手推一下,画一个表格。