1. 程式人生 > >卡特蘭數列(Catalan )

卡特蘭數列(Catalan )

簡述

卡特蘭數又稱卡塔蘭數,它是組合數學中一個常出現在各種計數問題中出現的數列,其前幾項為 : 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, ......

公式

1.遞迴公式1     f(n)=\sum_{i=0}^{n-1}f(i)*f(n-i-1)

2.遞迴公式2     f(n)=\frac{f(n-1)*(4*n-2)}{(n+1)}

3.組合公式1     f(n)=\frac{C_2_n^n}{n+1}

4.組合公式 2    f(n)=C_2_n^n-C_2_n^{n-1}

5.增長趨勢      f(n)\sim \frac{4^n}{{n^{\frac{3}{2}}}\sqrt{\pi }}

應用

  1. 二叉樹的計數:已知二叉樹有 n 個結點,求能構成多少種不同的二叉樹
  2. 括號化問題:一個合法的表示式由()包圍,()可以巢狀和連線,如:(())()也是合法表示式,現給出 n 對括號,求可以組成的合法表示式的個數
  3. 劃分問題:將一個凸 n+2 多邊形區域分成三角形區域的方法數
  4. 出棧問題:一個棧的進棧序列為1,2,3,..n,求不同的出棧序列有多少種
  5. 路徑問題:在 n*n 的方格地圖中,從一個角到另外一個角,求不跨越對角線的路徑數有多少種
  6. 握手問題:2n 個人均勻坐在一個圓桌邊上,某個時刻所有人同時與另一個人握手,要求手之間不能交叉,求共有多少種握手方法

This is the code

      f(n)=\sum_{i=0}^{n-1}f(i)*f(n-i-1)

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
long long cat[50];
long long Cat1(int n)
{
    memset(cat,0,sizeof(cat));
    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];
    }
    return cat[n];
}
int main()
{
    int n;
    scanf("%d",&n);
    printf("%lld\n",Cat1(n));
    return 0;
}

    f(n)=\frac{f(n-1)*(4*n-2)}{(n+1)}

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
long long cat[50];
long long Cat2(int n)
{
    memset(cat,0,sizeof(cat));
    cat[0]=1;
    for(int i=1;i<=n;++i)
    {
        cat[i]=((cat[i-1])*(i*4-2))/(i+1);
    }
    return cat[n];
}
int main()
{
    int n;
    scanf("%d",&n);
    printf("%lld\n",Cat2(n));
    return 0;
}

    f(n)=\frac{C_2_n^n}{n+1} 

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
long long cat[50];
long long tatal;
void Cat3(int n)
{
    tatal=1;
    for(int i=0;i<n;++i)//求c(2n,n);
        tatal=tatal*(2*n-i)/(i+1);
    tatal/=(n+1);
}
int main()
{
    int n;
    scanf("%d",&n);
    Cat3(n);
    printf("%lld\n",tatal);
    return 0;
}

  f(n)=C_2_n^n-C_2_n^{n-1}

兩個公式相當於一個,第一個是用第二個化簡來的

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
long long cat[50];
long long tatal;
void Cat4(int n)
{
    tatal=1;
    for(int i=0;i<n;++i)//求c(2n,n);
        tatal=tatal*(2*n-i)/(i+1);
    tatal=tatal-tatal*n/(n+1);
}
int main()
{
    int n;
    scanf("%d",&n);
    Cat4(n);
    printf("%lld\n",tatal);
    return 0;
}