catlan数
前言
卡特兰数在组合数里很难告诉它是什么?更多的情况是通过大量的例子来告诉你它怎么用。
从0开始catlan数的前几项为:
1,1,2,5,14,42,132,429,1430,4862,16796,58786,208012,742900,2674440,9694845,35357670,129644790…
定义
1. 递归定义
f n = f 0 ∗ f n − 1 + f 1 ∗ f n − 2 + f 2 ∗ f n − 3 + . . . . . + f n − 2 ∗ f 1 + f n − 1 ∗ f 0 {f_n=f_0*f_{n-1}+f_1*f_{n-2}+f_2*f_{n-3}+.....+f{n-2}*f_1+f_{n-1}*f_0} fn=f0∗fn−1+f1∗fn−2+f2∗fn−3+.....+fn−2∗f1+fn−1∗f0
2.递推关系
f n = 4 n − 2 n + 1 f n − 1 {f_n=\frac{4n-2}{n+1}f_{n-1}} fn=n+14n−2fn−1
3.通项公式
f n = 1 n + 1 C 2 n n {f_n=\frac{1}{n+1}C_{2n}^{n}} fn=n+11C2nn
⇒ f n = C 2 n n − C 2 n n − 1 {f_n=C_{2n}^{n}-C_{2n}^{n-1}} fn=C2nn−C2nn−1
但是对于catlan数列怎么用比它是什么更重要。
实例
例1
在一个𝑤×ℎ的网格上,你最开始在(0,0) 上,你每个单位时间可以向上走一格,或者向右走一格,在任意一个时刻,你往右走的次数都不能少于往上走的次数,问走到(𝑛,𝑛),有多少种不同的合法路径。
合法路径数为: C 2 n n − c 2 n n − 1 {C_{2n}^{n}-c_{2n}^{n-1}} C2nn−c2nn−1(catlan数)
后面的例子和证明我将引用一位大佬博客。
直接求不好,可以先找有多少种不合法路径。
路径总数为在2n次移动中选择n次向上移动,即
C
2
n
n
{C_{2n}^{n}}
C2nn
我们可以画一条
y
=
x
+
1
{y=x+1}
y=x+1的直线,(向右为x,向上为y,根据题意可以得出x-y≥0。那么不合法的为x-y<0,由于是整数格点,所以取<0的最大整数为-1,所以x-y=-1 ——>y=x+1)
发现所有合法路径都是不能碰这条线的,一旦碰到就说明向右的次数少于向上走的次数,是不合法路径。
先画一条不合法路径,那么这个不合法路径会与这条直线至少有一个交点,设这个交点为(a,a+1)。
那么这条不合法路径关于
y
=
x
+
1
{y=x+1}
y=x+1对称过去就是(n-1,n+1)
不难发现所有不合法路径最后都对应着一条到(n-1,n+1)的路径。
那么不合法所有路径为
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
例2(01序列)
你现在有n个0和n个1,问有多少个长度为2n的序列使得其中任意一个前缀中1的个数
都大于等于0的个数。
例如n=2时,
有1100,1010两种合法序列;
而1001,0101,0110,0011都是不合法序列。
合法的个数:
C
2
n
n
−
C
2
n
n
−
1
{C_{2n}^{n}-C_{2n}^{n-1}}
C2nn−C2nn−1
我们把出现1代表向右走一格,0代表向左走一格,那么这个问题和上面
拓展
如果是n个1,m个0。那么就是将终点改为(n,m)。
如果1的个数比0的个数多k个甚至更多,那么上下移动y=x这条直线即可。
例3(括号匹配)
你有n个左括号和n个右括号,问有多少种长度为2n的括号使得所有括号序列是合法的。
合法序列个数为:
C
2
n
n
−
C
2
n
n
−
1
{C_{2n}^{n}-C_{2n}^{n-1}}
C2nn−C2nn−1
要使所有括号合法,其实就是每个前缀中左括号数量不少于右括号数量。
将左括号看1,右括号看为0,和例2难道不是异曲同工之妙。
例4(进出栈问题)
有一个栈,我们有2n次操作,n次进栈,n次出栈,问有多少种进出栈顺序。
合法序列个数为:
C
2
n
n
−
C
2
n
n
−
1
{C_{2n}^{n}-C_{2n}^{n-1}}
C2nn−C2nn−1
同理,要是进出栈合法,那么每个前缀中进栈次数不能少于出栈的次数。
例5(312排列)
一个长度为n的排列a,只要满足
i
<
j
<
k
且
a
j
<
a
k
<
a
i
{i<j<k且a_j<a_k<a_i}
i<j<k且aj<ak<ai就称这个排列为312排列。
求n的全排列不是312排列的排列个数。
如果考虑
1
,
2
,
.
.
.
.
,
n
−
1
,
n
{1,2,....,n-1,n}
1,2,....,n−1,n的顺序进出栈。
通过分析我们得出312排列就是所有不能被表示出来的排列。那么此类问题又可以转化为进出栈问题。
例6(二叉树的构成问题)
有n个点,问这n个点最终能构成多少二叉树。
设i个点能构成
f
i
{f_i}
fi个二叉树
那么由题意得:
f
n
=
f
0
∗
f
n
−
1
+
f
1
∗
f
n
−
2
+
.
.
.
.
.
.
+
f
n
−
1
∗
f
0
{f_n=f_0*f_{n-1}+f_1*f_{n-2}+......+f_{n-1}*f_0}
fn=f0∗fn−1+f1∗fn−2+......+fn−1∗f0
剩下的的我不多说了吧,懂得都懂。
例7(凸多边形的三角划分)
一个凸的n边形,用n-3条不相交的对角线把它分为n-2个三角形,求不同的方法数目。
答案依然是: C 2 n n − C 2 n n − 1 {C_{2n}^{n}-C_{2n}^{n-1}} C2nn−C2nn−1
超级catlan数(施罗德数)
前几项为:1, 2, 6, 22, 90, 394, 1806, 8558, 41586, 206098,…
定义
递归定义
f n = f n − 1 + ∑ k = 0 n − 1 f k ∗ f n − 1 − k {f_n=f_{n-1}+\sum_{k=0}^{n-1}f_{k}*f_{n-1-k}} fn=fn−1+∑k=0n−1fk∗fn−1−k
相比卡特兰数,超级卡特兰数的唯一区别就是在递推的时候加了一个 f n − 1 {f_{n-1}} fn−1,那么其组合意义也可以看做是卡特兰数的扩展.
但如果按递归求的话时间复杂度会非常高,所以得对公式进行变化。
最后有人给出递推公式:
(
n
+
1
)
s
n
=
(
6
n
−
3
)
s
n
−
1
−
(
n
−
2
)
s
n
−
2
(
s
0
=
1
,
s
1
=
1
)
{(n+1)s_{n}=(6n-3)s_{n-1}-(n-2)s_{n-2}}(s_0=1,s_1=1)
(n+1)sn=(6n−3)sn−1−(n−2)sn−2(s0=1,s1=1)
这个数列
s
n
{s_n}
sn的前几项为:1, 1, 3, 11, 45, 197, 903, 4279, 20793, 103049…
这个公式里的数列除了第一项其它项都是超级catlan数(施罗德数)的一半,所以根据这个递推公式就可以在O(n)时间复杂度求出超级catlan数(施罗德数)。
实例
例1
和catlan数的例1很像,每次能往上,往右,这次多加了一个右上,求不超过y=x这条直线的方案数。
答案就是超级catlan数(施罗德数),n=1时,答案为1;n=2时,为2;n=3时,为6。