首先给出Catalan数的计算公式Catalan=C(2*n,n)/(n + 1)。
【解题思路】这道题目是典型的凸多边形划分问题,直接套用公式即可。
SOJ-2114(栈):典型的出栈顺序问题。
SOJ-2404(The midterm exam of algorithm):典型的二叉树个数问题。
SOJ-1247(球迷购票问题):
【题目描述】
球赛门票的售票处规定每位购票者限购一张门票,且每张门票售价50元。购票者中有m位手持50元钱币,另有n人手持100元。假设售票处开始售票时无零钱。问这m+n人有几种排队方式可使售票处不致出现找不出钱的局面。
对给定的m,n(0<=m,n<=5000),计算出排队方式总数。输入数据第1行为测试数据的个数t,余下的t行每行有两个整数m和n。对每一组测试数据输出方案数。
【解题思路】
当m<n显然无解;
对于m=n的情况就直接可以套用公式;
对于m>n的情况:
称由n-1个50元的和m+1个100元的构成的序列为sigma序列。
对于每种不合法的方式必然存在一种前缀使50元人数大于100元人数1个人,这样的方式有C(m+n,n-1),这种关系是对应的。
ans=C(m+n,n)-c(m+n,n-1)
具体解法参考《编程之美---买票找零》274-275页的分析。
运用了大数模版:
int main()
{
int m, n;
int t;
scanf("%d", &t);
while(t--) {
scanf("%d%d", &m, &n);
if (n > m) {
printf("0\n");
} else if (n == 0) {
printf("1\n");
} else if (n == m) {
bignum ans = ans.C(2 * n, n) / (n + 1);
cout<<ans<<endl;
} else {
bignum ans1 = ans1.C(m + n, n);
bignum ans2 = ans2.C(m + n, n - 1);
cout<<(ans1 - ans2)<<endl;
}
}
return 0;
}
卡特兰数
前几项为 : 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790, 477638700, 1767263190, 6564120420, 24466267020, 91482563640, 343059613650, 1289904147324, 4861946401452, ...