关于卡特兰数这玩意,其实最早是为了准备NOIP初赛而学的(包括斯特林数),不过那时候也没意识到它这么好玩。
这几天好像经常看到关于卡特兰数的一些应用,尤其是文化课数学正好在学计数,所以就决定写一篇总结一下。
为了给非竞赛生更好的阅读体验不至于一上来就被大量的公式劝退,我先介绍卡特兰数的应用,再推导公式。
当你看到这些时,它对应了卡特兰数
我们用
C
n
C_n
Cn表示第
n
n
n个卡特兰数,其中
n
∈
N
n\in\N
n∈N。它满足以下递推公式:
C
n
=
∑
i
=
0
n
−
1
C
i
C
n
−
1
−
i
=
∑
i
+
j
=
n
−
1
C
i
C
j
(
n
∈
N
∗
)
C_n=\sum\limits_{i=0}^{n-1}C_iC_{n-1-i}=\sum\limits_{i+j=n-1}C_iC_j(n\in\N^*)
Cn=i=0∑n−1CiCn−1−i=i+j=n−1∑CiCj(n∈N∗)
C
0
=
1
C_0=1
C0=1
另外还有一个更简洁的递推公式
C
n
=
4
n
−
2
n
+
1
C
n
−
1
C_n=\frac{4n-2}{n+1}C_{n-1}
Cn=n+14n−2Cn−1,但它的使用频率并不高。
以及通项
C
n
=
1
n
+
1
C
2
n
n
C_n=\frac{1}{n+1}C_{2n}^n
Cn=n+11C2nn。这个公式的推导我放在最后。
如果你发现你要解决的计数问题对应到以上公式,考虑卡特兰数。
应用举栗
- 【可接受数列问题】由
n
n
n个
−
1
-1
−1和
n
n
n个
+
1
+1
+1构成的长度为
2
n
2n
2n的数列
a
1
,
a
2
,
⋯
 
,
a
2
n
a_1,a_2,\cdots,a_{2n}
a1,a2,⋯,a2n,如果满足对于任意的
k
≤
2
n
k\leq2n
k≤2n且
k
∈
N
∗
k\in\N^*
k∈N∗都有
a 1 + a 2 + ⋯ + a k ≥ 0 a_1+a_2+\cdots+a_k\geq0 a1+a2+⋯+ak≥0
那么称这个数列是可接受的,否则是不可接受的。可以证明:可接受的数列个数是第 n n n个卡特兰数 C n C_n Cn。
证: 首先,由 n n n个 − 1 -1 −1和 n n n个 + 1 +1 +1构成的长度为 2 n 2n 2n的数列显然有 C 2 n n C_{2n}^n C2nn种,它们要么是可接受的,要么是不可接受的。我们想办法求出其中的不可接受的数列数量,将其减去即可。
考虑一个不可接受的数列,那么它一定存在第一个下标 k k k,满足
a 1 + a 2 + ⋯ + a k < 0 a_1+a_2+\cdots+a_k<0 a1+a2+⋯+ak<0
显然 k k k是一个奇数, a k = − 1 a_k=-1 ak=−1,并且前 k − 1 k-1 k−1个数中 − 1 -1 −1的个数和 + 1 +1 +1一样多。
下面我们做一个操作:将 a 1 , ⋯   , a k a_1,\cdots,a_k a1,⋯,ak这 k k k个数全部取相反数,即 + 1 +1 +1变为 − 1 -1 −1, − 1 -1 −1变为 + 1 +1 +1,那么 − 1 -1 −1的个数减少 1 1 1, + 1 +1 +1的个数增加 1 1 1,我们得到了一个由 ( n − 1 ) (n-1) (n−1)个 − 1 -1 −1和 ( n + 1 ) (n+1) (n+1)个 + 1 +1 +1构成的长度为 2 n 2n 2n的数列。
上述操作是可逆的。即,对于任意一个由 ( n − 1 ) (n-1) (n−1)个 − 1 -1 −1和 ( n + 1 ) (n+1) (n+1)个 + 1 +1 +1构成的数列,我们都可以找到其最小的下标 k k k满足前 k k k项之和大于 0 0 0(这样的 k k k显然存在),将这 k k k项取相反数,得到一个不可接受的数列。
所以,不可接受的数列与由 ( n − 1 ) (n-1) (n−1)个 − 1 -1 −1和 ( n + 1 ) (n+1) (n+1)个 + 1 +1 +1构成的长度为 2 n {2n} 2n的数列一样多,有 C 2 n n + 1 C_{2n}^{n+1} C2nn+1种。
因此,可接受的数列数量为 C 2 n n − C 2 n n + 1 C_{2n}^n-C_{2n}^{n+1} C2nn−C2nn+1,化简得它等于 1 n + 1 C 2 n n \frac{1}{n+1}C_{2n}^n n+11C2nn,为第 n n n个卡特兰数。 - 【下对角线格点路径问题】在直角坐标系中,从
(
0
,
0
)
(0,0)
(0,0)走到
(
n
,
n
)
(n,n)
(n,n),只能向右或向上走的所有格点路径中,只经过直线
y
=
x
y=x
y=x及其下方区域的点(不能穿过直线
y
=
x
y=x
y=x)的路径数为第
n
n
n个卡特兰数
C
n
C_n
Cn
证: 利用上一题的结论,不妨将向右走记为 + 1 +1 +1,向上走记为 − 1 -1 −1,那么每条路径都与一个由 n n n个 + 1 +1 +1和 n n n个 − 1 -1 −1构成的序列一一对应,而满足要求(即所谓“下对角线格点路径”)的格点路径对应的序列就是可接受序列,数量为 C n C_n Cn。
当 n n n不大时,本题还有一个简单易行的动态规划做法:设 f ( i , j ) f(i,j) f(i,j)表示从 ( 0 , 0 ) (0,0) (0,0)走到 ( i , j ) (i,j) (i,j)的下对角线格点路径数,当 i < j i<j i<j时 f ( i , j ) = 0 f(i,j)=0 f(i,j)=0,否则 f ( i , j ) = f ( i , j − 1 ) + f ( i − 1 , j ) f(i,j)=f(i,j-1)+f(i-1,j) f(i,j)=f(i,j−1)+f(i−1,j)。这个做法尤其对非竞赛生比较友好,因为它其实就是小学老师教过的在格点上标数字的做法:
其实可接受数列问题也可以转化成这道题然后采用这个做法,枚举量和思维量都比较小。当然了,真正算法竞赛里是肯定不会让这种做法拿到满分的。 - 【多边形的三角剖分问题】将一个凸
(
n
+
2
)
(n+2)
(n+2)边形通过连接
(
n
−
1
)
(n-1)
(n−1)条不相交的对角线的方式剖分成
n
n
n个三角形的方案数为第
n
n
n个卡特兰数
C
n
C_n
Cn。
证: 设 f n f_n fn表示凸 ( n + 2 ) (n+2) (n+2)边形三角剖分方案数,我们可以选定一个顶点 A 1 A_1 A1,从它出发连接两条线段 A 1 A i A_1A_i A1Ai和 A 1 A i + 1 A_1A_{i+1} A1Ai+1(允许其中的某一条是该多边形的边而非对角线),那么这两条线段和 A i A i + 1 A_iA_{i+1} AiAi+1构成了一个三角形。这也就把这个凸 ( n + 2 ) (n+2) (n+2)边形切成了一个凸 i i i边形 A 1 A 2 ⋯ A i A_1A_2\cdots A_i A1A2⋯Ai、一个三角形 A 1 A i A i + 1 A_1A_iA_{i+1} A1AiAi+1和一个凸 ( n − i + 3 ) (n-i+3) (n−i+3)边形 A 1 A i + 1 A i + 2 ⋯ A n + 2 A_1A_{i+1}A_{i+2}\cdots A_{n+2} A1Ai+1Ai+2⋯An+2,根据乘法原理,继续剖分的方案数为 f i − 2 f n − i + 1 f_{i-2}f_{n-i+1} fi−2fn−i+1,于是有
f n = ∑ i = 2 n + 1 f i − 2 f n − i + 1 = ∑ i = 0 n − 1 f i f n − 1 − i f_n=\sum\limits_{i=2}^{n+1}f_{i-2}f_{n-i+1}=\sum\limits_{i=0}^{n-1}f_if_{n-1-i} fn=i=2∑n+1fi−2fn−i+1=i=0∑n−1fifn−1−i
并且规定“二边形”三角剖分方案数为 1 1 1,有 f 0 = 1 f_0=1 f0=1
可以发现 f n = C n f_n=C_n fn=Cn,为第 n n n项卡特兰数。 - 【圆上的点连线问题】将圆上的
2
n
2n
2n个等分点成对地连线,使得这
n
n
n条线段互不相交的方案数为
C
n
C_n
Cn。
证: 设 f n f_n fn表示将圆上的 2 n 2n 2n个等分点成对连线,使得它们不相交的方案数。我们可以选定一个点 A 1 A_1 A1,任意连接一条线段 A 1 A i A_1A_i A1Ai。这里 i i i显然是偶数(否则它两侧的点的个数均为奇数,没有符合条件的方案),不妨用 2 i 2i 2i来表示,即连接线段 A 1 A 2 i A_1A_{2i} A1A2i,那么在它两侧的点数分别为 ( 2 i − 2 ) (2i-2) (2i−2)和 ( 2 n − 2 i ) (2n-2i) (2n−2i)个,根据乘法原理,继续连线的方案数为 f i − 1 f n − i f_{i-1}f_{n-i} fi−1fn−i。所以有
f n = ∑ i = 1 n f i − 1 f n − i = ∑ i = 0 n − 1 f i f n − 1 − i f_n=\sum\limits_{i=1}^nf_{i-1}f_{n-i}=\sum\limits_{i=0}^{n-1}f_if_{n-1-i} fn=i=1∑nfi−1fn−i=i=0∑n−1fifn−1−i
并且规定 n = 0 n=0 n=0时有一种方案
f 0 = 1 f_0=1 f0=1
不难发现 f n = C n f_n=C_n fn=Cn。 - 【二叉树计数问题】由
n
n
n个结点构成的不同形态的有根二叉树共有
C
n
C_n
Cn个,其中
C
n
C_n
Cn为第
n
n
n项卡特兰数。
仿照上例显然。 - 【进出栈序列问题】将
n
n
n个不同的元素依次进栈,可以得到不同的出栈序列有
C
n
C_n
Cn个。
令进栈为 + 1 +1 +1,出栈为 − 1 -1 −1,则变成了可接受数列问题。 - 【表达式运算顺序问题】考虑将
(
n
+
1
)
(n+1)
(n+1)个数相乘
a 1 a 2 ⋯ a n + 1 a_1a_2\cdots a_{n+1} a1a2⋯an+1
现在允许给这个表达式加括号来改变运算顺序,但是不可以改变它们的位置,即可以使用结合律但不能使用交换律,不同的运算顺序有 C n C_n Cn种。
同样从递推关系入手考虑即可得证。
公式推导
下面我们来推导卡特兰数通项公式
前置芝士:生成函数
设有数列 { f n } \{f_n\} {fn},其生成函数定义为 F ( x ) = f 0 + f 1 x + f 2 x 2 + ⋯ F(x)=f_0+f_1x+f_2x^2+\cdots F(x)=f0+f1x+f2x2+⋯,即 F ( x ) = ∑ k = 0 ∞ f k x k F(x)=\sum\limits_{k=0}^\infty f_kx^k F(x)=k=0∑∞fkxk,由于这里 x x x并无实际意义,规定 ∣ x ∣ < 1 ∣ f i ∣ |x|<\frac{1}{|f_i|} ∣x∣<∣fi∣1。
前置芝士:牛顿二项式定理
即二项式定理的扩展:
(
a
+
b
)
α
=
∑
k
=
0
∞
C
α
k
a
α
−
k
b
k
(a+b)^\alpha=\sum\limits_{k=0}^\infty C_\alpha^ka^{\alpha-k}b^k
(a+b)α=k=0∑∞Cαkaα−kbk,其中
α
\alpha
α是任意实数。
C
α
k
C_\alpha^k
Cαk为牛顿二项式系数,定义为
C
α
k
=
α
(
α
−
1
)
(
α
−
2
)
⋯
(
α
−
k
+
1
)
k
!
=
α
k
‾
k
!
C_\alpha^k=\frac{\alpha(\alpha-1)(\alpha-2)\cdots(\alpha-k+1)}{k!}=\frac{\alpha^{\underline{k}}}{k!}
Cαk=k!α(α−1)(α−2)⋯(α−k+1)=k!αk,其中
α
k
‾
\alpha^{\underline{k}}
αk称为
α
\alpha
α的
k
k
k次下降阶乘幂。(这个记号来源于《具体数学》)
设卡特兰数列生成函数
f
(
x
)
=
C
0
+
C
1
x
+
C
2
x
2
+
⋯
=
∑
k
=
0
∞
C
k
x
k
f(x)=C_0+C_1x+C_2x^2+\cdots=\sum\limits_{k=0}^\infty C_kx^k
f(x)=C0+C1x+C2x2+⋯=k=0∑∞Ckxk
(
f
(
x
)
)
2
=
C
0
C
0
+
(
C
0
C
1
+
C
1
C
0
)
x
+
(
C
0
C
2
+
C
1
C
1
+
C
2
C
0
)
x
2
+
⋯
(f(x))^2=C_0C_0+(C_0C_1+C_1C_0)x+(C_0C_2+C_1C_1+C_2C_0)x^2+\cdots
(f(x))2=C0C0+(C0C1+C1C0)x+(C0C2+C1C1+C2C0)x2+⋯
即
(
f
(
x
)
)
2
=
∑
k
=
0
∞
(
∑
i
+
j
=
k
C
i
C
j
)
x
k
(f(x))^2=\sum\limits_{k=0}^\infty\left(\sum\limits_{i+j=k}C_iC_j\right)x^k
(f(x))2=k=0∑∞⎝⎛i+j=k∑CiCj⎠⎞xk
将递推公式代入得到
(
f
(
x
)
)
2
=
∑
k
=
0
∞
C
k
+
1
x
k
(f(x))^2=\sum\limits_{k=0}^\infty C_{k+1}x^k
(f(x))2=k=0∑∞Ck+1xk
x
(
f
(
x
)
)
2
=
∑
k
=
0
∞
C
k
+
1
x
k
+
1
=
∑
k
=
1
∞
C
k
x
k
=
f
(
x
)
−
C
0
x(f(x))^2=\sum\limits_{k=0}^\infty C_{k+1}x^{k+1}=\sum\limits_{k=1}^\infty C_kx^k=f(x)-C_0
x(f(x))2=k=0∑∞Ck+1xk+1=k=1∑∞Ckxk=f(x)−C0
于是得到关于
f
(
x
)
f(x)
f(x)的二次方程
x
(
f
(
x
)
)
2
−
f
(
x
)
+
1
=
0
x(f(x))^2-f(x)+1=0
x(f(x))2−f(x)+1=0
利用求根公式解得
f
(
x
)
=
1
±
1
−
4
x
2
x
f(x)=\frac{1\pm\sqrt{1-4x}}{2x}
f(x)=2x1±1−4x
注意到
f
(
x
)
f(x)
f(x)必须满足
f
(
0
)
=
C
0
=
1
f(0)=C_0=1
f(0)=C0=1。当
f
(
x
)
=
1
−
1
−
4
x
2
x
f(x)=\frac{1-\sqrt{1-4x}}{2x}
f(x)=2x1−1−4x时,利用洛必达法则可得
lim
x
→
0
f
(
x
)
=
1
\lim\limits_{x\to0}f(x)=1
x→0limf(x)=1符合。然而当
f
(
x
)
=
1
+
1
−
4
x
2
x
f(x)=\frac{1+\sqrt{1-4x}}{2x}
f(x)=2x1+1−4x时,不难发现它在
0
0
0处的极限不存在(为无穷大),舍去。
所以
f
(
x
)
=
1
−
1
−
4
x
2
x
f(x)=\frac{1-\sqrt{1-4x}}{2x}
f(x)=2x1−1−4x
利用牛顿二项式定理展开,最终可以得到
f
(
x
)
=
∑
k
=
0
∞
(
2
k
)
!
(
k
+
1
)
!
k
!
x
k
f(x)=\sum\limits_{k=0}^\infty\frac{(2k)!}{(k+1)!k!}x^k
f(x)=k=0∑∞(k+1)!k!(2k)!xk
所以
C
n
=
(
2
n
)
!
(
n
+
1
)
!
n
!
=
1
n
+
1
C
2
n
n
C_n=\frac{(2n)!}{(n+1)!n!}=\frac{1}{n+1}C_{2n}^n
Cn=(n+1)!n!(2n)!=n+11C2nn
如果希望得到本文一开始提到的那个更简洁的递推公式,只需将两项的通项相除即可。
练习:
- 更一般地,从 ( 0 , 0 ) (0,0) (0,0)走到 ( n , m ) (n,m) (n,m)( n ≥ m n\geq m n≥m)的下对角线格点路径数是多少?
- [TJOI2015]概率论:由 n n n个顶点随机生成的有根二叉树期望有多少个叶节点?
- 我也想不到有什么别的练习题了…
参考资料:《组合数学(原书第5版)》 by Richard A. Brualdi