康托展开是一个全排列到一个自然数的双射,常用于构建哈希表时的空间压缩。 康托展开的实质是计算当前排列在所有由小到大全排列中的顺序,因此是可逆的。
X=an(n−1)!+an−1(n−2)!+...a10!
其中 ai为整数,并且满足 0≤ai<i,1≤i≤n 。
ai 表示原数的第 i 位在当前未出现的元素中排在第几。
例如:在 12345 的排列组合中,计算 34152的康托展开值。
值 | 未出现且小于当前值的数 | 展开值 | |
---|---|---|---|
3 | 1,2=>a5=2 | a5×4! | 48 |
4 | 1,2=>a4=2 | a4×3! | 12 |
1 | 无 =>a3=0 | a3×2! | 0 |
5 | 2=>a2=1 | a2×1! | 1 |
2 | 无 =>a1=0 | a1×0! | 0 |
所以比 34152 小的组合有 61 个,即 34152是排第 62 。
康托展开是一个全排列到一个自然数的双射,因此是可逆的。即对于上述例子,在给出 61 可以算出起排列组合为 34152。由上述的计算过程逆推回来,具体过程如下:
61/4!=2 余 13 ,说明,说明比首位小的数有 2 个,所以首位为 3 。
13/3!=2 余 1 ,说明,说明在第二位之后小于第二位的数有 2 个,所以第二位为 4 。
1/2!=0 余 1 ,说明,说明在第三位之后没有小于第三位的数,所以第三位为 1 。
用 1/1!=1 余 0 ,说明,说明在第四位之后小于第四位的数有 1 个,所以第四位为 5 。
最后一位自然就是剩下的数 2 。通过以上分析,所求排列组合为 34152。
题目:
考虑0, 1, 2,共3个数字的所有排列,按字典序排列为
012 021 102 120 201 210
输入n,考虑0, 1, 2, 3, 4, 5, 6, 7, 8 和 9 共10个数字的所有排列,按字典序排,第n个是什么?
第一行输入组数T, 接下来T行,每行一个整数n。 (1 <= T <= 20,0 <= n <= 1000000)
对于每组数据,输出一个排列,10个数字,中间不加空格。
10 1 2 6 24 120 720 5040 40320 362880 1000000
0123456789 0123456798 0123456987 0123459876 0123498765 0123987654 0129876543 0198765432 0987654321 2783915460
按照康托展开逆运算的方式,还原排列即可。