卡特兰数专题
卡特兰数
原理
摘自百度,为什么摘百度呢?
因为百度比我写得好。
关于卡特兰数的一些应用
1、矩阵链乘: P=a1×a2×a3×……×an,依据乘法结合律,不改变其顺序,只用括号表示成对的乘积,有几种括号化的方案?
2、一个栈(无穷大)的进栈序列为1,2,3,…,n,有多少个不同的出栈序列?
3、n个节点构成的二叉树,共有多少种情形?
4、求一个凸多边形区域划分成三角形区域的方法数?
5、在圆上选择2n个点,将这些点成对链接起来使得所得到的n条线段不相交,一共有多少种方法?(下图供参考)
6、n*n的方格地图中,从一个角到另外一个角,不跨越对角线的路径数为h(n).例如, 4×4方格地图中的路径有:
7、n层的阶梯切割为n个矩形的切法数也是Cn。如下图所示:
8、有2n个人排成一行进入剧场。入场费5元。其中只有n个人有一张5元钞票,另外n人只有10元钞票,剧院无其它钞票,问有多少中方法使得只要有10元的人买票,售票处就有5元的钞票找零?
9、甲乙两人比赛乒乓球,最后结果为20∶20,问比赛过程中甲始终领先乙的计分情形的种数。
10、2n个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,问排列方式有多少种?
都是对卡特兰数的一些应用题,有一些细节的变换,(实际上可以用一份代码略改全过)。。
以其中对多边形对角线分割三角形的代码为例:
#include<iostream>
#include<algorithm>
#include<stack>
#include<vector>
#include<queue>
#include<cstdio>
#include<cstdlib>
#include<cmath>
using namespace std;
long long a[55];
int main()
{
int n;
cin >> n;
a[2] = 1;
for(int i = 3;i <= n;i++)
{
for(int j = 2;j < i;j++)
{
a[i] += a[j] * a[i - j + 1];
}
}
cout << a[n];
return 0;
}
就是经典的卡特兰数计算方式。
一些实现方式
{
int i, j, len, carry, temp;
a[1][0] = b[1] = 1;
len = 1;
for(i = 2; i <= 100; i++)
{
for(j = 0; j < len; j++) //乘法
a[i][j] = a[i-1][j]*(4*(i-1)+2);
carry = 0;
for(j = 0; j < len; j++) //处理相乘结果
{
temp = a[i][j] + carry;
a[i][j] = temp % 10;
carry = temp / 10;
}
while(carry) //进位处理
{
a[i][len++] = carry % 10;
carry /= 10;
}
carry = 0;
for(j = len-1; j >= 0; j--) //除法
{
temp = carry*10 + a[i][j];
a[i][j] = temp/(i+1);
carry = temp%(i+1);
}
while(!a[i][len-1]) //高位零处理
len --;
b[i] = len;
}
嘛这几道题代码都比较简单就不列了,实际上思想是一致的,但推倒过程可能不一,殊途同归吧。