A - Buy the Ticket——卡特兰数
题目链接:HDU - 1133
讲这道题之前,决定先讲一下卡特兰数;
卡特兰数是组合数学中一个很著名的数列。
它的第n项可以用以下几种公式得出:
- 递推公式1
f(x)=i=0∑n−1f(i)×f(n−i−1). - 递推公式2
f(n)=n+1f(n−1)∗(4∗n−2) - 组合公式1
f(n)=n+1C2nn - 组合公式2
f(n)=C2nn−C2nn−1
基本模型
就是给你两种数1,-1各n个,让你把这2*n个数排个序列,要满足1~k (1<=k<=2∗n)上数之和要大于0。问你有多少种排列方式。
这个问题的答案就是卡特兰数 f(n);
了解了卡特兰数之后,我们再来看这道题。
题目大意
有面值50和100的两种钱币,现在有一些人要去一个景区旅游,它的门票50元,但是景区的人没有零钱,一旦出现一个人给100找不开的情况,就结束。问你现在有n个人拿着100,有m个人拿着50的钱币,有多少种排序方式让他们都可以进入景区。
思路
首先我们想,如果n>m,那么怎么也是不能全进入的,所以是0.
然后现在就是m>=n的情况。看的大牛的博客。
但是这道题对人的顺序也是有区别的,所以还要乘上 m!∗n!
AC代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
int a[2005];
void mu(int k)
{
int c=0;
for(int i=1;i<=2000;i++)
{
int u=a[i]*k+c;
a[i]=u%10;
c=u/10;
}
}
int main()
{
int n,m;
int k=1;
while(~scanf("%d %d",&m,&n))
{
if(n==0&&m==0)
{
break;
}
memset(a,0,sizeof(a));
printf("Test #%d:\n",k++);
if(n>m)
{
printf("0\n");
}
else
{
int s=m+1-n;
if(n==0)
{
a[1]=1;
}
else
{
int p=1;
while(s)
{
a[p++]=s%10;
s/=10;
}
}
for(int i=1; i<=n+m; i++)
{
if(i==m+1)
{
continue;
}
mu(i);
}
int flog=0;
for(int i=2000;i>=1;i--)
{
if(a[i]!=0)
{
flog=1;
}
if(flog==1)
{
printf("%d",a[i]);
}
}
printf("\n");
}
}
return 0;
}