[数论] 卡特兰数

LAST UPD:2023/09/10 更新了部分例题。

引入 · 基本模型

\(n\) 个元素进栈序列为 \(1,2,3,4\dots n\)。求有多少种出栈序列

我们需要确保最后一次操作后,栈中没有元素。因此,共有 \(2n\) 次操作。(每个元素进栈一次,出栈一次)

对于每次操作,如果我们想出栈,则它一定要有数字可以 pop。如果我们把栈抽象成一条链,若第 \(k\) 次想要出栈,则必须满足 \(sum_k \geq 0\)\(sum_k\) 表示前 \(k\) 个操作的前缀和)

我们先不考虑不合法的序列,则共有 \(C_{n}^{2n}\) 种方案。也就是在 \(2n\) 次操作中选 \(n\) 个标记为 \(1\)\(1,-1\) 一定是一一对应的。

对于不合法的序列呢?

举个例子:对于不合法序列 \(+1,-1,-1,+1,-1,+1\) , 显然从第 \(3\) 位就不合法。若对前 \(3\) 位进行取反,即序列变成 \(-1,+1,+1,+1,-1,+1\)。容易发现变成了 \(n+1\)\(1\)

那么这个性质是否存在普遍性?

我们找的是第一个前缀和小于 \(0\) 的位置,因此它的前缀和一定是 \(-1\)。它前面的 \(-1\) 一定比 \(1\) 多一个。若取反,则 \(1\)\(-1\) 多一个。就会导致 \(1\) 变成 \(n+1\) 个,\(-1\) 变成 \(n-1\) 个。

取反后的序列和取反前的序列一定是一一对应的。也就是从取反后的序列一定能变换成唯一的取反前的序列。

因此,不合法的序列个数等于 \(C_{n+1}^{2n}\)。 这里运用了转换法。因为取反前和取反后的序列一一对应,所以找取反后的序列个数即为不合法的方案个数。

所以,合法的出栈数量应为:

\[C^{2n}_n-C^{2n}_{n+1}=\frac{C^{2n}_n}{n+1} \]

其中 \(\frac{C^{2n}_n}{n+1}\) 即为卡特兰数的通项公式。


定义

卡特兰数有多个定义方式,例如递归定义:

\[C_n=\sum \limits_{k=0}^{n-1}C_kC_{n-1-k}=C_0C_{n-1}+C_1C_{n-2}+\dots+C_{n-1}C_0 \]

这个式子我们可以用凸多边形拆分三角形问题推导。下文也会提到。

递推关系

\[C_n=\frac{4n-2}{n+1}C_{n-1} \]

因此,只要我们发现题目中的数据具有以上任意一种关系,那么题目就迎刃而解,因为这就是卡特兰数列。

以及上文提到的通项公式:

\[\frac{C^{2n}_n}{n+1} \]

直接阅读可能非常抽象,接下来我们给出几个卡特兰数的典型例题。事实上很多题目都是和上面的进出栈问题是一样的。


典例1:01序列

你有 \(n\)\(0\)\(n\)\(1\)。请构造一个长度为 \(2n\)\(01\) 序列,使得任意一个前缀中 \(1\) 的个数大于 \(0\) 的个数,求有多少种构造方式。

不妨把 \(0\) 看作类似于上述出栈问题的 \(-1\)。对于总共的方案数显然是 \(C^{2n}_n\) 。对于不合法的方案数,我们仍像上面引入的问题一样,找到第一个前缀和为 \(-1\) 的不合法位置,对它即它前面的每个数取反。因此不合法的方案数是 \(C^{2n}_{n+1}\)

总共的方案数即为 \(C^{2n}_n-C^{2n}_{n+1}\)

典例2:括号匹配

你有 \(n\) 个左括号,\(n\) 个右括号,请把它们配成合法的括号序列,求方案个数。

把左括号看作 \(-1\),右括号看作 \(+1\) 。然后就是和上面的思考方式一样了。

典例3:球迷购票问题

\(n\) 个人有 50 元的钱,\(n\) 个人有 \(100\) 元的钱,请求出有多少种合法排列,使得售票员不会找不出钱(售票员一开始没有钱)

\(50\) 元钱的人看作 \(+1\)\(100\) 元钱的看作 \(-1\)。然后就是卡特兰数。

由此可见,卡特兰数本质上就是将 不合法的方案映射。找到第一个不合法的位置,将其以及前面所有操作取反进行映射。

典例4:平面直角坐标系中的路径问题

在平面直角坐标系中,你将从 \((0,0)\) 走到 \((n,n)\)。你不得越过直线 \(y=x\)(可以走上去)。求有多少种不同的路径方案。

乍看是一个 dfs。如果看不出性质我们可以先打表处理,再观察性质。

先不考虑限制条件,则共有 \(C^{2n}_n\) 中方案。因为最后要走到 \((n,n)\)。所以一定是向上走 \(n\) 步,向右走 \(n\) 步的。

image

显然,直线 \(BC\) 为函数 \(y=x+1\)。因为不能越过 \(y=x\) 即不能碰到 \(y=x+1\)

路径 \(DEFKHIJKLM\) 显然不是一个合法路径。它第一次碰到 \(y=x+1\) 的点为 \((2,3)\)。如果把它以及前面的操作全都取反,即向上变成向右,向右变成向上。则
image

可以发现终点变成 \((n,n-1)\)。向上走 \((n-1)\) 步,向右走 \((n+1)\) 步。

所以,答案就转换为 \(C^{2n}_n-C^{2n}_{n+1}\)

上述都是直接线性理解卡特兰数,接下来我们来看一下递归求卡特兰数的形式。

典例4:凸多边形划分三角形

在对角线不相交的情况下,将一个正多边形划分成若干个三角形,求划分方案数。

考虑动态规划。

容易证明,凸多边形的任意一条边最后一定被分在一个三角形中,因此我们可以先把这个三角形拿出来再考虑分解。

image

我们以正六边形举例,固定两个点 \(A,N\)。再在集合 \({A+1,N-1}\) 中任意选取一个点 \(k\)。连接 \(A,k,N\)。构造一个三角形。

我们这样的做法是先将这个三角形取出,再分别处理被三角形分成的两部分。

这个三角形将正六边形分为了两部分,分别是正 \(k\) 边形,正 \(n-k+1\) 边形。

对于选择的点 \(k\)。它的分割方案数为 \(f_k\times f_{n-k+1}\)

对于正 \(n\) 边形,显然分割方案数为:

\[f_n=\sum \limits_{i=2}^{n-1} f_i f_{n-i+1} \]

显然对于点 \(A,N\) 任选两个相邻的点都不会影响答案。

这就是卡特兰数列的递归定义形式。用卡特兰数列的递推式求解即可。

posted @   SXqwq  阅读(277)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示