康拓展开
Posted ticmis
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了康拓展开相关的知识,希望对你有一定的参考价值。
数论 康拓展开
前言
额,好像鸽了太久了。为了找回手感,不管是什么先写一点
简介
康托展开是一个全排列到一个自然数的双射,常用于构建哈希表时的空间压缩。 康托展开的实质是计算当前排列在所有由小到大全排列中的顺序,因此是可逆的。
——摘自百度百科
虽然解释得比较规范,但也比较容易理解
康拓展开就是对全排列排序,以此解决空间过大的问题
朴素算法
现在我们面对着这样一个问题:在特定情境下,我们需要为全排列数赋值,那我们怎么处理?
一种做法就是直接用Long Long存,但缺点显而易见:空间招架不住
另外一种做法是用map存。说实话我不知道有什么太大的问题,貌似是可以的。不过STL这种东西,能不用就不用 真香
康托展开
先上公式:
定义:
(a[x]=位置x后的数字中,小于位置x上数字的个数)
公式:
(f=sum_{i=1}^{n} a[i]*(n-i)!)
公式比较抽象,但胜在美观嘛
怎么去理解呢?我们用34152这个例子来理解
- 观察第一位"3":当第一位是"1","2"时,全排列数肯定比该数要小;当第一位时"3"时,排名先后位置;当第一位是"4","5"时:全排列数肯定比该数要大。那么a[1]=2;
- 观察第二位"4":接着上一次的结果继续讨论,由于首位是"3"未知的,所以首位确定为"3"。此时,如果第二位如果是"1","2",则排列数肯定比原数要小;如果是"4",则未知;如果是"5",则肯定大,因此a[2]=2
- 继续讨论下去,相同道理
结果:
(f=2*4!+2*3!+0*2!+1*1!+0*0!=61)
康托逆展开
顾名思义,康托展开解决的是用全排列数到排名,那么康托逆展开就用排名还原出全排列数
思考一下康托展开是怎么实现的,它有点类似于一个特殊进制数,每(n)位的意义是(n!),那么只要除回去即可
依旧以34152为例,康托值为61
- 用 61 / 4! = 2余13,说明 ,说明比首位小的数有2个,所以首位为3。
- 用 13 / 3! = 2余1,说明 ,说明在第二位之后小于第二位的数有2个,所以第二位为4。
- 用 1 / 2! = 0余1,说明 ,说明在第三位之后没有小于第三位的数,所以第三位为1。
- 用 1 / 1! = 1余0,说明 ,说明在第二位之后小于第四位的数有1个,所以第四位为5。
还原出来34152
事实上,做题过程中,还是康托展开用的多,康托逆展开实际用处并不是很大
代码
code:
思路简单,代码易写,懒得复制粘贴ˋ( ° ▽、° )
以上是关于康拓展开的主要内容,如果未能解决你的问题,请参考以下文章