Skip to content

生成排列和组合

生成排列

Stirling公式: $$ n! = \sqrt{2 \pi n}(\frac{n}{e})^n $$ 给定一个整数 \(k\) ,赋予其一个方向得 \(\overrightarrow{k}\)\(\overleftarrow{k}\),如果一个整数指向的相邻数比它要小,则这个整数是可移动的

生成 \(\{1, 2, \cdots, n\}\) 的排列的算法: 从 \(\overleftarrow{1} \overleftarrow{2} \cdots \overleftarrow{n}\) 开始,当存在可移动整数时,

  1. 找出最大的可移动整数 \(m\)
  2. 交换 \(m\) 和它指向的相邻整数
  3. 交换所有满足 \(p > m\) 的整数 \(p\) 的箭头方向

《组合数学》P56

排列中的逆序

\(i_1 i_2 \cdots i_n\)\(\{1, 2, \cdots, n\}\) 的一个排列,如果 \(k < l\)\(i_k > i_l\) ,则称数对 \((i_k, i_l)\) 为一个逆序 (inversion)

\(a_j\) 为排列中在 \(j\) 前又大于 \(j\) 的整数个数

数值序列 \(a_1, a_2, \cdots, a_n\) 叫做排列 \(i_1 i_2 \cdots i_n\)逆序列。例如: 31524 的逆序列是 1,2,0,1,0

定理\(b_1, b_2, \cdots, b_n\) 是满足以下条件的整数序列: $$ 0 \leqslant b_1 \leqslant n-1, 0 \leqslant b_2 \leqslant n-2, \cdots, 0 \leqslant b_{n-1} \leqslant 1, b_n = 0 $$ 那么,一定存在唯一一个 \(\{1, 2, \cdots, n\}\) 的排列,它的逆序列是 \(b_1, b_2, \cdots, b_n\)

证明思路: 找出唯一的排列即可

按照逆序个数的奇偶性把一个排列称为奇排列偶排列

生成组合

\(S = \{x_{n-1}, \cdots, x_1, x_0\}\),想将 \(S\) 的所有子集列出

  • 对应二进制数 \(\Rightarrow\) 字典序/压缩序
  • Gray码

Gray码定义

截屏2025-04-12 16.50.58

生成Gray码相当于沿着 \(n\) 方体的边遍历该 \(n\) 方体,经过每个角点恰好一次

截屏2025-04-12 16.55.25

二阶Gray生成三阶Gray: “投影”到后边再补1。通过这种方式构建的Gray码叫反射Gray码

递归定义:

截屏2025-04-12 17.01.44

生成Gray码的算法

以反射Gray码的顺序生成 \(0,1\)\(n\) 元组的算法:

\(a_{n-1}a_{n-2}\cdots a_0\)\(0\)\(1\)\(n\) 元组,则 \(\sigma(a_{n-1}a_{n-2}\cdots a_0) = a_{n-1} + a_{n-2} + \cdots + a_0\) 是其中 \(1\) 的个数

截屏2025-04-12 17.20.20

证明 证明这个算法确实产生的是反射Gray码

  • \(n = 1\) 时,显然成立

  • \(n>1\) 且对于 \(n-1\) 这个算法产生 \(n-1\) 阶反射Gray码

  • Gray码的前 \(2^{n-1}\) 是在所有数前补0,而算法生成的前 \(2^{n-1}\) 个也是一样的(0不影响)

  • Gray码的后半部分,假设有 $$ 1a_{n-2}\cdots a_0 $$

    \[ 1b_{n-2}\cdots b_0 \]

    说明 \(n-1\) 阶Gray码有 $$ b_{n-2}\cdots b_0 $$

    \[ a_{n-2}\cdots a_{0} \]

    \(\sigma(a_{n-2}\cdots a_0)\)\(\sigma(b_{n-2}\cdots b_0)\) 的奇偶性相反,\(\sigma(1a_{n-2}\cdots a_0)\)\(\sigma(a_{n-2}\cdots a_0)\) 的奇偶性也相反。假设 \(\sigma(b_{n-2}\cdots b_0)\) 为偶,则通过改变 \(b_0\) 得到 \(a_0\) ,算法中将把 \(1a_{n-2}\cdots a_0\) 中的 \(a_0\) 修改;假设 \(\sigma(b_{n-2}\cdots b_0)\) 为奇……

思考: 给出一个Gray码,问它是Gray码表中的第几个?

截屏2025-05-04 18.19.43

生成 \(r\) 子集

我们想让所有 \(r\) 子集按一定顺序出现,先定义集合的字典序: 两个集合 \(A\)\(B\) ,只在两集合中的一个的最小整数在 \(A\) 中,则称在字典序中 \(A\) 先于 \(B\) (为了便于观察,把子集中的元素按从小到大的顺序写)

找直接后继的方法:

截屏2025-05-04 19.35.49

确定某一子集的位置:

截屏2025-05-04 19.40.11

证明 先计算出现在 \(a_1a_2\cdots a_r\) 后面的 \(r\) 子集的数目:

  • \(a_1a_2\cdots a_r\) 后且第1个元素比 \(a_1\) 大的子集有 \(\binom{n-a_1}{r}\) (只选 \(r\) 个比 \(a_1\) 大的数即可)
  • \(a_1a_2\cdots a_r\) 后且第1个元素是 \(a_1\) 但第二个元素大于 \(a_2\) 的子集有 \(\binom{n-a_2}{r-1}\)
  • ……

偏序和等价关系