标题表示了一种在春节期间坚持更新BLOG的行为艺术。。
下边开始正式介绍:卡特兰数(Catalan Number)
定义(第N个卡特兰数用h(n)表示):令h(0)=1,h(1)=1,则catalan数满足关系式:
h(n)=h(0)h(n-1)+h(1)h(n-2)+.....+h(n-1)h(0)
即h(2)=h(0)h(1)+h(1)h(0)=2
h(3)=h(0)h(2)+h(1)h(1)+h(2)h(0)=5
......
应用:
1、给定N个节点,能够组成多少种不同的二叉树?
2、一个无穷栈的进栈序列为1..2...n,有多少种不同的出栈序列
3、P=a1*a2*a3*a4*.......an,用括号表示成对的乘积,有多少种方案?
答案: h(n)
。。。
示例代码(HDU1023):点击打开链接
讨论火车的出栈次序,用卡特兰数模板套用即可。需要注意的是卡特兰数一般都很大。
#include <iostream> #include <stdio.h> #include <cmath> using namespace std; int a[105][105]; //大数卡特兰数,第二维为某位数 int b[105]; //卡特兰数的长度 void catalan() //求卡特兰数 { 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; } } int main() { int i, n; catalan(); while(cin>>n) { for(i = b[n]-1; i>=0; i--) { cout<<a[n][i]; } cout<<endl; } return 0; }