目录
- 概述和基础概念
- 排列
- 组合
- 插板法
- 斯特林数
- 第一类
- 第二类
- 错排问题
- 卡特兰数
- 多重集的排列组合
- Prüfer 序列
- 排列组合在 OI 中的技巧
- 引用
概述和基础概念
组合数学是 OI 中的一个重要考点。在开始讲解组合数学之前,我们先确立几个概念:
阶乘:一个正整数的阶乘为从1开始连续到这个数的乘积,记为\(n!\)。对于一个数的阶乘可以写作:
\[ n! = 1\times 2\times 3\times \dots \times n, n \in N^* \]
排列
排列(permutation)是用于解决下面这个问题而诞生的运算:
求从 n 个元素中取出 k 个元素,k 个元素的排列数量。
那么,我们可以把这个问题写作\( P_n^k \)。我们可以来推出这个问题的通解。首先确定范围,显然有\(k \leq n\)。之后,我们发现对于每一次取出元素的方案数与取出元素的次序有关,当我们第\(k\)次选取元素时,我们发现我们有\(n-k+1\)个选择;当我们第\(k-1\)次选取元素时,我们有\(n-k+2\)种选择…以此类推,通过乘法原理我们可以得出以下算式:
\[ P_n^k = n \times (n-1) \times (n-2) \times \dots \times (n-k+1) \]
通过我们上面介绍的阶乘,我们可以化简为:
\[ P_n^k = \frac{n!}{(n-k)!} \]
组合
组合其实是排列的“弱化版”。组合专注于解决这样的问题:
求从 n 个元素中取出有 k 个元素的集合,问集合的选取方案。
那么这就非常显然了,我们只需在排列问题上进行重复方案的消去即可。具体答案为:
\[ {n \choose k} = \frac{P_n^k}{k!} = \frac{n!}{(n-k)!k!} \]
插板法
插板法其实在高考数学中经常用到,我在这里简述一些经典问题便结束对插板法的表述。
例题 把一行\(n\)个人划分成\(d\)组,试问有多少种方案。
解 我们注意到\(n\)个人中有\(n-1\)个缝隙,可以把问题转换为\(n-1\)个缝隙中选\(d\)个的方案数,答案显然为\(n-1 \choose d\)。
斯特林数
第一类
还没学,弃坑。
第二类
例题:P1655:小朋友的球
斯特林数主要解决的问题是这样的:
第二类Stirling数是 n 个元素中定义 k 个等价类的方法数目。——Wikipedia
其递推公式为:
\[S(n, k) = S(n-1,k-1)+kS(n-1,k)\]
具体解释:递推关系的说明:考虑第n个物品,n可以单独构成一个非空集合,此时前n-1个物品构成k-1个非空的不可辨别的集合,有\(S(n-1,k-1)\)种方法;也可以前n-1种物品构成k个非空的不可辨别的集合,第n个物品放入任意一个中,这样有\(k*S(n-1,k)\)种方法。(src:Wikipedia)
例题代码:
# P1655.py MAX_N = 405 stiring = [[0]*MAX_N for i in range(MAX_N)] for i in range(1, MAX_N): stiring[i][i] = stiring[i][1] = 1 for j in range(2, i): stiring[i][j] = stiring[i - 1][j - 1] + j * stiring[i - 1][j] while True: try: n, m = map(int, input().split()) print(stiring[n][m]) except EOFError: break
错排问题
错排问题指的是这样一类问题:
设排列长度为\(n\),问每个数都不在自己位置上的方案数为多少?
卡特兰数
卡特兰数递推式为:
\[ Cat_n = \frac{2n \choose n}{n+1} \]
卡特兰数的意义为:
给定一个长度为\(n\)的序列,第\(i\)位\(0\)的前缀个数为\(zero[i]\),\(1\)的前缀个数为\(one[i]\)。对于每一个\(i \leq n\),都有\(zero[i] \geq one[i]\)。
以下几个问题都与卡特兰数有关:
- 合法的括号序列数量
- \(n\)个节点的满二叉树数量
- 直角坐标系上从\((0,0)\)走到\((n,n)\)且不经过直线\(y=x\)的路径数量为\(2Cat_{n-1}\)。
- \(n\)个元素的进出栈序列数量
- \(Cat_n\)表示通过连结顶点而将\(n+2\)边的凸多边形分成三角形的方法个数。
- \(Cat_n\)表示用\(n\)个长方形填充一个高度为\(n\)的阶梯状图形的方法个数。
卡特兰数的证明
在这里我们来证明为什么卡特兰数可以代表合法的括号序列数量。(下面证明思路来自于《组合数学》第 8 章第一节)
多重集的排列组合
多重集的定义
多重集的组合问题
Prüfer 序列与无根树
正常情况下,一个无根树的表现形式大多都是图片或者是边的三元组集。现在我来介绍一种序列,可以与一棵无根树的形态对应,以便我们对其进行排列组合方面的探究。首先下图这棵树对应的 Prüfer 序列为:\(4,4,4,5\)。
我来描述一下如何把一颗无根树转换为一个 Prufer 序列:
- 找到编号最小的叶子节点,删除它并把唯一与之相接的节点加入 Prufer 序列中。
- 重复第一个步骤,直到树只剩下两个节点。
我们可以发现,一个节点在 Prufer 序列中出现的次数是该节点的度减一,且这个序列的长度为\(n-2\)。所以,因为这两个性质,产生了一些公式。
引理1 节点个数为\(n\)的、形态不同的无根树有\(n^{n-2}\)种。
这个很好理解,把长度为\(n-2\)的 Prufer 序列对应到无根树上,排列组合可得。
引理2 如果给定点的个数\(n\)与每一个点的度数\(d_i\),则不同形态的树有\(\frac{(n-2)!}{\prod_{i = 1}^n (d_i-1)!}\)种。
这个其实就是多重集的排列。长度为\(n-2\)的 Prufer 序列种存在\(d_i-1\)个的第\(i\)个点,我就不再赘述了。
引用
sources:
https://oi-wiki.org/math/stirling/
https://zh.wikipedia.org/wiki/%E9%94%99%E6%8E%92%E9%97%AE%E9%A2%98
https://zh.wikipedia.org/wiki/%E5%8D%A1%E5%A1%94%E5%85%B0%E6%95%B0