組合數學——卡特蘭數

首先聲明這篇博文是我在蒐集衆多資料的基礎上寫的,這裏一次性給出所有資料出處,正文中間不再贅述。

http://baike.baidu.com/link?url=7BdjPnf-tbSAnkXFIF_G8NHOZxYXo4uPfNiQ4eeyxCIjGx2CM4jt6PnFkyeKsyYtxZXML7q_7IULkxxOd_8pNq

http://baike.baidu.com/link?url=ajn4IlGPUsSqM8Re1L5MAO3hDEqrewST3ffh7pkCp-tmExrYtnML5wlbiihRk3vfnmWECc7B6fvasCnudMGEhckZAXZ6XrdSvCHvQ7hQ1PQqNuoDu5_X5i0WIqmvXRHjNvbfaTZqRFd0xkAjKRSVRK

http://blog.csdn.net/hackbuteer1/article/details/7450250

http://www.cnblogs.com/ShaneZhang/p/4102581.html

http://blog.csdn.net/wuzhekai1985/article/details/6764858

一、定義

令h(0)=1,h(1)=1,卡塔蘭數數滿足遞歸式:
h(n)= h(0)*h(n-1) + h(1)*h(n-2) + ... + h(n-1)h(0) (其中n>=2),這是n階遞推關係;
還可以化簡爲1階遞推關係: 如h(n)=(4n-2)/(n+1)*h(n-1)(n>1) h(0)=1
該遞推關係的解爲:h(n)=C(2n,n)/(n+1)=P(2n,n)/(n
+1)!=(2n)!/(n!*(n+1)!) (n=1,2,3,...)

遞推關係的另類解爲:h(n)=c(2n,n)-c(2n,n-1)(n=0,1,2,...)

卡塔蘭數列的前幾項爲(sequence A 0 0 0 1 0 8 in OEIS) [注: n = 0, 1, 2, 3, … n]

1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790, 477638700, 1767263190, 6564120420, 24466267020, 91482563640, 343059613650, 1289904147324, 4861946401452, …

二、應用及證法、轉換方法

NO.1

問題等價於:n個1和n個0組成一2n位的2進制數,要求從左到右掃描,1的累計數不小於0的累計數,試求滿足這條件的數有多少?
解答: 設P2n爲這樣所得的數的個數。在2n位上填入n個1的方案數爲 C(n 2n)
不填1的其餘n位自動填以數0。從C(n 2n)中減去不符合要求的方案數即爲所求。
不合要求的數指的是從左而右掃描,出現0的累計數超過1的累計數的數。
不合要求的數的特徵是從左而右掃描時,必然在某一奇數2m+1位上首先出現m+1個0的累計數,和m個1的累計數。
此 後的2(n-m)-1位上有n-m個1,n-m-1個0。如若把後面這部分2(n-m)-1位,0與1交換,使之成爲n-m個0,n-m-1個1,結果得 1個由n+1個0和n-1個 1組成的2n位數,即一個不合要求的數對應於一個由n-1個1和n+1個0組成的一個排列。
反過來,任何一個 由n+1個0,n-1個1組成的2n位數,由於0的個數多2個,2n是偶數,故必在某一個奇數位上出現0的累計數超過1的累計數。同樣在後面的部分,令0 和 1互換,使之成爲由n個0和n個1組成的2n位數。即n+1個0和n-1個1組成的2n位數,必對應於一個不合要求的數。
用上述方法建立了由n+1個0和n-1個1組成的2n位數,與由n個0和n個1組成的2n位數中從左向右掃描出現0的累計數超過1的累計數的數一一對應。
例如 10100101
是由4個0和4個1組成的8位2進制數。但從左而右掃描在第5位(顯示爲紅色)出現0的累計數3超過1的累計數2,它對應於由3個1,5個0組成的10100010。
反過來 10100010
對應於 10100101
因而不合要求的2n位數與n+1個0,n-1個1組成的排列一一對應,故有
P2n = C(n 2n)— C(n+1 2n)
這個結果是一個“卡塔蘭數”Catalan

卡特蘭數的簡單代碼實現(因爲數實在太大了,我又懶得寫高精度,所以就來個水的。這個代碼主要是照着百度百科上抄的,但是那個代碼認真看就發現錯誤百出,汗!)

<span style="font-size:18px;">#include<iostream>
#include<cstdio>
using namespace std;
long long f[35];
int main()
{
    cout<<"卡特蘭數到F[n]:";
    int n;
    cin>>n;
    f[0]=1;
    printf("1 ");
    for(int i=1;i<=n;i++)
    {
        f[i]=(4*i-2)*f[i-1]/(i+1);
        printf("%I64d ",f[i]);
    }
    return 0;
}</span>

NO.2

問題描述:
12個高矮不同的人,排成兩排,每排必須是從矮到高排列,而且第二排比對應的第一排的人高,問排列方式有多少種?
這個筆試題,很YD,因爲把某個遞推關係隱藏得很深。
問題分析:
我們先把這12個人從低到高排列,然後,選擇6個人排在第一排,那麼剩下的6個肯定是在第二排.
用0表示對應的人在第一排,用1表示對應的人在第二排,那麼含有6個0,6個1的序列,就對應一種方案.
比如000000111111就對應着
第一排:0 1 2 3 4 5
第二排:6 7 8 9 10 11
010101010101就對應着
第一排:0 2 4 6 8 10
第二排:1 3 5 7 9 11
問題轉換爲,這樣的滿足條件的01序列有多少個。
觀察1的出現,我們考慮這一個出現能不能放在第二排,顯然,在這個1之前出現的那些0,1對應的人
要麼是在這個1左邊,要麼是在這個1前面。而肯定要有一個0的,在這個1前面,統計在這個1之前的0和1的個數。
也就是要求,0的個數大於1的個數。
這樣我們就把問題轉換成前一個問題,OK解決!


NO.3

N個節點的二叉樹有多少種形態

先考慮只有一個節點的情形,設此時的形態有f(1)種,那麼很明顯f(1)=1
如果有兩個節點呢?我們很自然想到,應該在f(1)的基礎上考慮遞推關係。那麼,如果固定一個節點後,有兩種情況,一是左子樹還剩一個節點,此刻類型數量爲f(1),第二 種情況是右子樹生一個節點,此刻類型數量爲f(1),固有f(2) = f(1) + f(1)
如果有三個節點呢?我們需要考慮固定兩個節點的情況麼?當然不行,爲什麼?
因爲當節點數量大於等於2時,無論你如何固定,其形態必然有多種,而在這多種基礎之上你如何安排後續剩下的節點呢?所以必須挑出這個誤區。
回到二叉樹的定義,二叉樹本質上就是一個遞歸的形式,左子樹,右子樹,根節點。所以根節點應該不變,需要遞歸處理的是左右子樹。
也就是說,還是考慮固定一個節點,即根節點。好的,按照這個思路,還剩2個節點,那麼左右子樹的分佈情況爲2=0+2=1+1=2+0。
所以有3個節點時,遞歸形式爲f(3)=f(2) + f(1)*f(1) + f(2). (注意這裏的乘法,因爲左右子樹一起組成整棵樹,根據排列組合裏面的乘法原理即可得出)
那麼有n個節點呢?我們固定一個節點,那麼左右子樹的分佈情況爲n-1=n-1 + 0 = n-2 + 1 = ... = 1 + n-2 = 0 + n-1
OK。遞歸表達式出來了f(n) = f(n-1) + f(n-2)f(1) + f(n-3)f(2) + ... + f(1)f(n-2) + f(n-1)

<span style="font-size:18px;">//函數功能: 計算Catalan的第n項
//函數參數: n爲項數
//返回值:   第n個Catalan數
int Catalan(int n)
{
	if(n <= 1)
		return 1;

	int *h = new int [n+1]; //保存臨時結果
	h[0] = h[1] = 1;        //h(0)和h(1)
	for(int i = 2; i <= n; i++)    //依次計算h(2),h(3)...h(n)
	{
		h[i] = 0;
		for(int j = 0; j < i; j++) //根據遞歸式計算 h(i)= h(0)*h(i-1)+h(1)*h(i-2) + ... + h(i-1)h(0)
			h[i] += (h[j] * h[i-1-j]);
	}
	int result = h[n]; //保存結果
	delete [] h;       //注意釋放空間
	return result;
}</span>


NO.4

n對括號有多少種匹配方式?

思路:n對括號相當於有2n個符號,n個左括號、n個右括號,可以設問題的解爲f(2n)。第0個符號肯定爲左括號,與之匹配的右括號必須爲第2i+1字符。因爲如果是第 2i個 字符,那麼第0個字符與第2i個字符間包含奇數個字符,而奇數個字符是無法構成匹配的。
通過簡單分析,f(2n)可以轉化如下的遞推式 f(2n) = f(0)*f(2n-2) + f(2)*f(2n - 4) + ... + f(2n - 4)*f(2) + f(2n-2)*f(0)。簡單解釋一下,f(0) * f(2n-2)表示第0個字符與第1個字 符匹配,同時剩餘字符分成兩個部分,一部分爲0個字符,另一部分爲2n-2個字符,然後對這兩部分求解。f(2)*f(2n-4)表示第0個字符與第3個字符匹配,同時剩餘字符分成 兩 個部分,一部分爲2個字符,另一部分爲2n-4個字符。依次類推。
假設f(0) = 1,計算一下開始幾項,f(2) = 1, f(4) = 2, f(6) = 5。結合遞歸式,不難發現f(2n) 等於h(n)。


NO.5

矩陣鏈乘: P=a1×a2×a3×……×an,依據乘法結合律,不改變其順序,只用括號表示成對的乘積,試問有幾種括號化的方案?

思路:可以這樣考慮,首先通過括號化,將P分成兩個部分,然後分別對兩個部分進行括號化。比如分成(a1)×(a2×a3.....×an),然後再對(a1)和(a2×a3.....×an)分別括號化;又如分成(a1×a2)×(a3.....×an),然後再對(a1×a2)和(a3.....×an)括號化。
設n個矩陣的括號化方案的種數爲f(n),那麼問題的解爲
f(n) = f(1)*f(n-1) + f(2)*f(n-2) + f(3)*f(n-3) + f(n-1)*f(1)。f(1)*f(n-1)表示分成(a1)×(a2×a3.....×an)兩部分,然後分別括號化。
計算開始幾項,f(1) = 1, f(2) = 1, f(3) = 2, f(4) = 5。結合遞歸式,不難發現f(n)等於h(n-1)。


NO.6

一個棧(無窮大)的進棧序列爲1,2,3,…,n,有多少個不同的出棧序列?

思路:這個與加括號的很相似,進棧操作相當於是左括號,而出棧操作相當於右括號。n個數的進棧次序和出棧次序構成了一個含2n個數字的序列。第0個數字肯定是進棧的數,這個數相應的出棧的數一定是第2i+1個數。因爲如果是2i,那麼中間包含了奇數個數,這奇數個肯定無法構成進棧出棧序列。
設問題的解爲f(2n), 那麼f(2n) = f(0)*f(2n-2) + f(2)*f(2n-4) + f(2n-2)*f(0)。f(0) * f(2n-2)表示第0個數字進棧後立即出棧,此時這個數字的進棧與出棧間包含的數字個數爲0,剩餘爲2n-2個數。f(2)*f(2n-4)表示第0個數字進棧與出棧間包含了2個數字,相當於1 2 2 1,剩餘爲2n-4個數字。依次類推。
假設f(0) = 1,計算一下開始幾項,f(2) = 1, f(4) = 2, f(6) = 5。結合遞歸式,不難發現f(2n) 等於h(n)。


NO.7

n個節點構成的二叉樹,共有多少種情形?

思路:可以這樣考慮,根肯定會佔用一個結點,那麼剩餘的n-1個結點可以有如下的分配方式,T(0, n-1),T(1, n-2),...T(n-1, 0),設T(i, j)表示根的左子樹含i個結點,右子樹含j個結點。
設問題的解爲f(n),那麼f(n) = f(0)*f(n-1) + f(1)*f(n-2) + .......+ f(n-2)*f(1) + f(n-1)*f(0)。假設f(0) = 1,那麼f(1) = 1, f(2) = 2, f(3) = 5。結合遞推式,不難發現f(n)等於h(n)。


NO.8

在圓上選擇2n個點,將這些點成對連接起來使得所得到的n條線段不相交的方法數?

思路:以其中一個點爲基點,編號爲0,然後按順時針方向將其他點依次編號。那麼與編號爲0相連點的編號一定是奇數,否則,這兩個編號間含有奇數個點,勢必會有個點被孤立,即在一條線段的兩側分別有一個孤立點,從而導致兩線段相交。設選中的基點爲A,與它連接的點爲B,那麼A和B將所有點分成兩個部分,一部分位於A、B的左邊,另一部分位於A、B的右邊。然後分別對這兩部分求解即可。
設問題的解f(n),那麼f(n) = f(0)*f(n-2) + f(2)*f(n-4) + f(4)*f(n-6) + ......f(n-4)*f(2) + f(n-2)*f(0)。f(0)*f(n-2)表示編號0的點與編號1的點相連,此時位於它們右邊的點的個數爲0,而位於它們左邊的點爲2n-2。依次類推。
f(0) = 1, f(2) = 1, f(4) = 2。結合遞歸式,不難發現f(2n) 等於h(n)。


NO.9

求一個凸多邊形區域劃分成三角形區域的方法數?

思路:以凸多邊形的一邊爲基,設這條邊的2個頂點爲A和B。從剩餘頂點中選1個,可以將凸多邊形分成三個部分,中間是一個三角形,左右兩邊分別是兩個凸多邊形,然後求解左右兩個凸多邊形。
設問題的解f(n),其中n表示頂點數,那麼f(n) = f(2)*f(n-1) + f(3)*f(n-2) + ......f(n-2)*f(3) + f(n-1)*f(2)。f(2)*f(n-1)表示三個相鄰的頂點構成一個三角形,那麼另外兩個部分的頂點數分別爲2和n-1。
設f(2) = 1,那麼f(3) = 1, f(4) = 2, f(5) = 5。結合遞推式,不難發現f(n) 等於h(n-2)。


NO.10

有2n個人排成一行進入劇場。入場費5元。其中只有n個人有一張5元鈔票,另外n人只有10元鈔票,劇院無其它鈔票,問有多少中方法使得只要有10元的人買票,售票處就有5元的鈔票找零?
思路:可以將持5元買票視爲進棧,那麼持10元買票視爲5元的出棧。這個問題就轉化成了棧的出棧次序數。由應用三的分析直接得到結果,f(2n) 等於h(n)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章