康托展开与逆康托展开
闲话
仍想起曾经自己在网上查阅算法时的崩溃,今天来重新学习这个算法时,感觉释然了许多......
康托展开
康托展开常用来求解这样一个问题:
给定一个序列a包含 1~n ,求这个序列在 1~n 的全排列中,按字典序排第几个。
说枯燥点儿,它就是这个式子:
其中 \(b_i\) 表示其右边比 \(a_i\) 小的数的个数。
怎么去理解这个式子呢?举个例子:
求序列{3,4,1,2,5}关于原问题的答案
在这里只给出3,4的解释。
1.对于3,其右边有两个数1,2比之小,说明1,2作第一位的已经跳过了,然后因为第一位后面有4位,4位的全排列为4!,因此贡献为\(2\times4!\)
2.对于4,其右边同样有两个数1,2比之小,说明1,2作第二位的已经跳过了,然后因为第二位后面有3位,3位的全排列为3!,因此贡献为\(2\times3!\)
以此类推后,发现答案为60,可正确答案为61。
那么为什么要加一呢?
可以发现序列{1,2,3,4,5}答案为0。
因为康托展开的式子是以0开头的,但是正常计算需要+1 很少听到第0个序列的说法
逆康托展开
类似这样一个问题:
给定一个序列a在 1~n 的全排列中按字典序排第几个,求这个序列
实质就是康托倒着问
所以我们倒着做
我们先将给出的字典序减1,然后列出后缀积
| 1 | 2 | 3 | 4 | 5 | |
|---|---|---|---|---|---|
| 120 | 24 | 6 | 2 | 1 | 1 |
| 5! | 4! | 3! | 2! | 1! | 0! |
拿61举例子:
61 - 1 = 60
60 / 4! = 2 ……12 在{1,2,3,4,5}有2个比它小 即3
12 / 3! = 2 …… 0 在{1,2,4,5}有2个比它小 即4
0 / 2! = 0 …… 0 在{1,2,5}有0个比它小 即1
0 / 1! = 0 …… 0 在{2,5}有0个比它小 即2
0 / 0! = 0 …… 0 在{5}有0个比它小 即5
所以编号为61的答案序列为{3,4,1,2,5}

浙公网安备 33010602011771号