康托展开与逆康托展开

闲话

仍想起曾经自己在网上查阅算法时的崩溃,今天来重新学习这个算法时,感觉释然了许多......

康托展开

康托展开常用来求解这样一个问题:

给定一个序列a包含 1~n ,求这个序列在 1~n 的全排列中,按字典序排第几个。

说枯燥点儿,它就是这个式子:

\[ans=b_n(n-1)!+b_{n-1}(n-2)!+...+b_1 0! \]

其中 \(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}


posted @ 2022-09-15 20:03  Tonvia  阅读(22)  评论(0)    收藏  举报
#Snow{ position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 99999; background: rgba(125,137,95,0.1); pointer-events: none; }