红魔咖啡馆

头发越掉越多,头发越掉越少

0%

【数学】Catalan数

Catalan数

该数列经常出现在计数问题中

特征

递推关系

\[ C_n = \begin{cases} 1, & n = 0, \\ \sum_{i=0}^{n-1} C_{i}C_{n-1-i}, & n > 0. \end{cases} \] 前几项为\(1,1,2,5,14,42,132,429,1430,\cdots\)

常见表达式

$C_n = = ,~ n. $

$ C_n = - ,~n .$

$ C_n = C_{n-1},~ n > 0,~ C_0 = 1.$

前两个形式将它转换为阶乘和组合数的计算问题,第三个形式则提供了顺次计算的递推公式

应用

规模为\(n\)的计数问题\(C_n\),可以通过枚举分界点,拆分为两个规模分别为\(i\)\((n-1-i)\)的子问题

因此Catalan数广泛用于各类具有类似递归结构的问题中

路径计数问题

有一个大小为\(n\times n\)的方格图,左下角为\((0,0)\),右上角为\((n,n)\),从左下角开始,每次向右或向上走一单位,不走到\(y=x\)上方(但可以触碰)的情况下,到达右上角的路径总数为\(C_n\)

总的路径数为 \(\binom{2n}{n}\)。不合法的路径恰好可以与到 \((n,n+1)\) 的路径建立一一对应,从而得到不合法路径数为 \(\binom{2n}{n+1}\),所以合法的为二者之差。

圆内不相交弦计数/圆上点配对问题

圆上有\(2n\)个点,将这些点成对连接起来且使得所得到的\(n\)条线段两两不相交的方案数是\(C_n\)

将点按顺序编号,考虑与编号1配对的点k,将圆分成两部分,每部分再独立配对,得到递推

多边形剖分三角计数问题

对角线不相交的情况下,将一个凸\(n+2\)边形区域分为三角形区域的方法数为\(C_n\)

固定某个顶点,把与该顶点连成三角形的另一顶点作为切点,分割成左右两个子问题,变为递推形式

二叉树计数问题

含有\(n\)个结点的形态不同的二叉树数目为\(C_n\)。等价的,含有\(n\)个非叶结点的形态不同的满二叉树数目为\(C_n\)

含有\(n\)内部结点的满二叉树个数为\(C_n\)

选择某个元素作根,左子树大小为 \(i\),右子树大小为 \(n−1−i\),左右子树独立,乘法得到递推。

括号序列计数问题

\(n\)对括号构成的合法括号序列数为\(C_n\)

可以映射为路径问题

出栈序列计数问题/避免模式排列问题

一个栈进栈序列为\(1,2,3,\cdots,n\),合法出栈序列数目为\(C_n\)

可以映射为括号序列问题

数列计数问题

\(n\)\(+1\)\(n\)\(-1\)组成的数列\(a_1,a_2, \ldots ,a_{2n}\),部分和满足\(a_1+a_2+ \ldots +a_k \geq 0~(k=1,2,3, \ldots ,2n)\)的数列数目为\(C_n\)

可以映射为括号序列问题

e.g. P1044 栈

1
2
3
4
5
6
7
8
9
10
11
12
13
vector<ll> cat(20);
void init(){
  cat[0]=cat[1]=1;
  for (int i = 2;i<20;i++){
    cat[i] = cat[i-1]*(4*i-2)/(i+1);

  }
}
void solve() {
  int n;
  cin >> n;
  cout << cat[n]<<endl;
}