Catalan数的试题链接:POJ 2084 链接游戏
题目答案代码:
#include <cstdio> #include <cstring> #include <cmath> #include <iostream> #include <algorithm> #include <vector> #include <stack> #include <sstream> #include <map> #include <set> #include <queue> #include <stdlib.h> using namespace std; #define MAX 100 #define BASE 10000 int a[105][100]; void multiply(int a[],int b) //大数乘法(万进制) { int array=0; for(int i=99;i>=0;i--) { // b 从99到0 依次 * a[i] array += b*a[i]; a[i] = array%10000; array /= 10000; } } void divide(int a[],int b) //大数除法(万进制) { int div=0; for(int i=0;i<100;i++) { div =div * 10000 + a[i]; a[i] = div/b; div%=b; } } //卡特兰数的解法: //h(n) = h(n-1) * (4n-2) / (n+1) //前四项过程 //h[1] = 1 //h[2] = 1 * 6 / 3 = 2 //h[3] = 2 * 10 / 4 = 5 //h[4] = 5 * 14 / 5 = 14 int main() { int n; a[1][99]=1; // 将第一项变为1(99是最低位,相当于个位) for(int i=2;i<=100;i++) { memcpy(a[i],a[i-1],sizeof(a[i-1])); //将a[i-1]赋给a[i],从第二项开始 // 将a[1]赋给a[2] // 对memcpy的解释: // char a[100]={'a','b','c','d'}; // char b[100]; // memcpy(b,a,sizeof(a)); 将a复制到b里面,复制的个数是a的长度 // cout << b << endl; // 输出结果:abcd multiply(a[i],4*i-2); //大数乘法 divide(a[i],i+1); //大数除法 } while(cin>>n) { int i=0; if(n==-1) break; for (i=0;i<100;i++) { if(a[n][i]==0) continue; else break; } cout << a[n][i++];//最高项,不用填零补位 for(;i<100;i++) printf("%04d",a[n][i]); //必须是%04d,换成%4d或者%d都是错误的(不是最高项,要填零补位) //知识点: // %d左对齐,输出变量的所有数字; // %4d右对齐,宽度为4,左边填充空格,当变量的实际宽度大于4时,输出变量的所有数字; // %04d与%4d的唯一区别就是左边填充0。 cout<<endl; } return 0; }
Catalan数时组合数学中一个常出现在各种计数问题中的数列。前几项为(从0开始):1,1,2,5,14,42,132......
定义:
令h(1)=1,h(0)=1
Catalan数满足递归式:
h(n)=h(0)*h(n-1)+h(1)*h(n-2)+......h(n-1)h(0) (n>=2)
另类递归式:
h(n)=[(4*n-2)/(n+1)]*h(n-1). => h(n)=h(n-1)*(4n-2) / n+1
该递归关系的解为:
h(n)=C(2n,n)/(n+1) (n=1,2,3,~~) => h(n)=(2n)!/[n!*(n+1)!]
狄忒公式的另类解为:
h(n)=C(2n,n)-C(2n,n-1) 或者 h(n)=C(2n,n)-C(2n,n+1)
Catalan数应用举例:
(1)一个栈(无穷大)的进栈顺序为1,2,3,···,n,问有多少个不同的出栈顺序??
简单说明:
对于每一个数来说,必须进栈一次,出栈一次。我们把进栈设为状态“1”,出栈设为状态“0”。
从2n位二进制中填入n个1的方案数是:C(2n,n),不填1的其余n位自动填0.从中减去不符合要求的方案数即为所求。
不符合要求的2n位数与n+1个0,n-1个1组成的排列一一对应。
显然,不符合要求的方案数为C(2n,n+1).
所以最终的答案就是:C(2n,n)-C(2n,n+1) (就是卡特兰数的公式)
(2)凸多边形三角划分
在一个凸多边形中,通过若干条互不相交的对角线,把这个多边形划分成若干个三角形,求不同的方案数f(n)。
如果n是如多边形的边数,则
f(3)=1;
f(4)=2;
f(5)=5;
f(6)=14;
。。。跟卡特兰数差不多,推后两个数。
(3)n对括号正确匹配问题
给定n对括号,求括号正确配对的字符串数,例如:
0对括号:[空序列] 1种可能
1对括号:() 1种可能
2对括号:()() (()) 2种可能
3对括号:((())) ()(()) ()()() (())() (()()) 5种可能
那么问题来了,n对括号有多少种正确配对的可能呢?