卡特兰数又称卡塔兰数,英文名Catalan number,是组合数学中一个常出现在各种计数问题中出现的数列。以比利时的数学家欧仁·查理·卡塔兰 (1814–1894)的名字来命名,其前几项为 : 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, …
Catalan的递推关系
令
cat[0]=cat[1]=1;
for(int i=2;i<=n;++i)
for(int j=0;j<i;++j)
cat[i]+=cat[j]*cat[i-j-1];
递推复杂度为O(n^2)
令
则有
cat[0]=cat[1]=1;
for(int i=2;i<=n;++i)
cat[i]=cat[i-1]*(4*i-2)/(i+1);
递推复杂度为O(n)
或
代码先坑着= =
Catalan的应用
入栈出栈
Q:给定n个数,进栈的序列是1,2,3,4,…..n,有多少个不同的出栈次序
A:
h(n)表示个数为n的序列的出栈次序种数
假设最后出栈的元素是k
在k入栈前k前面的元素都出栈,所以有
k后面的元素在k之前出栈,所以有
运用乘法原理有
由于k可以取1到n,根据加法原理得
也就是卡特兰数得递推式
平衡括号
Q:有n个左括号,n个右括号,总共2*n个括号,有多少种合法匹配方式,
A:
将左括号视为入栈,右括号视为出栈
那么这个问题就转化成了将n个左括号入栈,有多少种合法出栈次序得问题
也就是上面的出栈入栈问题,答案就是
二叉树的形态
Q:有n个结点得二叉树,可以有多少种不同形态
A:
以h(n)表示有n个节点的二叉树可以有得不同形态数
假设其根得左子树有k个节点
那么其左子树有
根据乘法原理
k可以取0-n
则有
满足卡特兰数递推式
走方格
Q:一个 n*n 的方格,从左下角走到右上角,只能向右和向上走,但是不能绕过左下角和右上角确定的对角线,问有多少种走法?
A:
要走到右上角,需要向右走n布,向上走n步
向右走看作进栈,向左走看作出栈,本质就是n个数出栈次序的问题
还有很多应用
待更。。。。
Catalan数例题
题目背景
盛况空前的足球赛即将举行。球赛门票售票处排起了球迷购票长龙。
按售票处规定,每位购票者限购一张门票,且每张票售价为50元。在排成长龙的球迷中有N个人手持面值50元的钱币,另有N个人手持面值100元的钱币。假设售票处在开始售票时没有零钱。试问这2N个球迷有多少种排队方式可使售票处不致出现找不出钱的尴尬局面。
题目描述
例如当n=2是,用A表示手持50元面值的球迷,用B表示手持100元钱的球迷。则最多可以得到以下两组不同的排队方式,使售票员不至于找不出钱。
第一种:A A B B
第二种:A B A B
对于给定的n (0≤n≤20),计算2N个球迷有多少种排队方式,可以使售票处不至于找不出钱。
输入格式:
一个整数,代表N的值
输出格式:
一个整数,表示方案数
分析
一个A买票后售票处就积累50元钱
一个B买票需要售票处找零50元钱
说明在一个B买票前至少需要一个A买过票
那么我们就可以将A看作左括号,B看作右括号
问题就是要求合法得括号匹配,即Catalan数
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef long long ll;
int n;
ll cat[50];
int main()
{
scanf("%d",&n);
cat[0]=cat[1]=1;
for(int i=2;i<=n;++i)
cat[i]=cat[i-1]*(4*i-2)/(i+1);
cout<<cat[n];
return 0;
}