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对括号有多少种正确配对的可能呢?