康托展开

问题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} icdot i! < n!$.

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

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

原文地址:https://www.cnblogs.com/Patt/p/6039263.html