卡特兰数
卡特兰数是组合数学中一个常出现在各种计数问题中的数列。
数列前几项:1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862,16796…
递推公式h(n)=((4*n-2)/(n+1))*h(n-1);
一、推导
一般树的递归表示导致其生成函数的隐函数定义
G(z) = z/( 1-G(z) )
解G实数解得
G(z)=1/2*(1-(√1-4z))
由二项展开公式
(1+x)^a^=1+(a/1!)x+(a(a-1)/2!)x^2^+...
代入a=1/2,x=-4z,
得
G(z) =z+z^2^+2z ^3^+5z^4^+14z^5^+ 42z^6^+ 132z^7^+....
数 Cn=(2n)!/(n+1)!n!
生成函数C(z)=(1-(√1-4z))/2z 称为Catalan数
一般树的枚举问题可归结为计算Catalan数
二、例题
括号生成
数字 n(1<=n<=8) 代表生成括号的对数,请你算出所有可能的并且有效的括号组合的个数
例如:
输入:n = 3
满足的组合:“((()))”,“(()())”,“(())()”,“()(())”,“()()()”,输出:5
输入格式:
输入在一行中给出n
输出格式:
输出个数
输入样例:
在这里给出一组输入。例如:
3
输出样例:
在这里给出相应的输出。例如:
5
代码长度限制
16 KB
时间限制
1000 ms
内存限制
128 MB
bfs:
#include<iostream>
#include<queue>
using namespace std;
int cnt;//n<=8
int main()
{
int n,z,y;
queue<int>q;//zuo
queue<int>p;//you
cin>>n;
q.push(1);
p.push(0);
while(!q.empty())
{
z=q.front();
y=p.front();
q.pop();
p.pop();
if(z+y+1==2*n){cnt++;continue;}
if(z+1<=n){q.push(z+1);p.push(y);}
if(y+1<=z){p.push(y+1);q.push(z);}
}
cout<<cnt;
}
catalan:
#include<stdio.h>
#include<string.h>
int ans[102][100];//高精度,一行一个数
void list()
{
ans[0][0]=ans[1][0]=1;
int i,j;
for(i=2;i<102;i++)
{
int c=0;
for(j=0;j<100;j++)
{
ans[i][j]=ans[i-1][j]*(4*i-2)+c;
c=ans[i][j]/10;
ans[i][j]%=10;
}
int z=0;
for(j=99;j>=0;j--)
{
z=z*10+ans[i][j];
ans[i][j]=z/(i+1);
z%=(i+1);
}
}
}
int main(){
int t;
list();
while(~scanf("%d",&t))
{
int i=99;
if(t==-1)
break;
while(ans[t][i]==0)
i--;
for(;i>=0;i--)
printf("%d",ans[t][i]);
printf("\n");
}
return 0;
}
n对括号生成,凸n+2边形三角剖分,n个元素进出栈序列等可看成构造有n+1个叶子节点的满二叉树的计数问题,均符合卡特兰数的递归定义。
三、几何意义
https://blog.csdn.net/chenlong_cxy/article/details/113613203