康托展开

问题1

给出一个\(1 \sim n\)的全排列\(P\), 求它是所有全排列的第几个 (0-based)?

做法

从左到右看\(P\)的每一位, 考虑当前可以确认有多少全排列在\(P\)之前.
\(*\): 所有第一位是\(1 \sim P_1 -1\)的排列都在\(P\)之前, 共有 \((P_1-1)(n-1)!\)个.
\(P_1, *\): 所有第一位是\(P_1\), 第二位小于\(P_2\)的全排列都在\(P\)之前, 共有\(less_P(2) \cdot (n-2)!\)个.
\(less_P(k)\): \(\{P_{k+1}, P_{k+2}, \dots, P_{n}\}\)中小于\(P_k\)的数的数目.

\[Rank(P) = \sum_{i=1}^{n}less_P(i) \cdot (n-i)! \]

借助这个公式, 可以把一个全排列压缩成一个整数, 范围是\([0, n!-1]\), 这个方法称作康托展开.

问题2

给出一个\(1 \sim n\)的全排列\(P\)的序号\(rank(P)=x\), 求出这个全排列. (逆康托展开)

做法

从上面的讨论可知, \(x\)可以看成一个\(n\)为数, 从左 (高位) 到右 (低位) 每一位的权值分别是\((n-1)!,\ (n-2)!,\ \dots,\ 1!,\ 0!\), 即$x=d_{1}d_{2}...d_{3}d_{n},\ d_i = less_P(i) \le n-i $.

类似\(k\)进制, 我们有

\[\sum_{j=i}^{n}(n-j) \cdot (n-j)! < (n-i+1)! \]

下面证明\(\sum \limits _{i=0}^{n-1} i\cdot i! < n!\).

证明: 对\(n\)用归纳法, \(n=1\)时显然.
\(\sum \limits _{i=0}^{n} i\cdot i! < n! + n\cdot n! =(n+1)n! = (n+1)!\)

这样我们就能求出\(less_P(1)\)\(less_P(n)\), 从而求出\(P_1\)\(P_n\).

posted @ 2016-11-07 15:58  Pat  阅读(135)  评论(0编辑  收藏  举报