码迷,mamicode.com
首页 > 其他好文 > 详细

康拓展开

时间:2020-06-29 22:39:24      阅读:78      评论:0      收藏:0      [点我收藏+]

标签:公式   问题:   顺序   问题   先后   哈希   相同   说明   自然数   

数论 康拓展开

前言

额,好像鸽了太久了。为了找回手感,不管是什么先写一点

简介

康托展开是一个全排列到一个自然数的双射,常用于构建哈希表时的空间压缩。 康托展开的实质是计算当前排列在所有由小到大全排列中的顺序,因此是可逆的。

——摘自百度百科

虽然解释得比较规范,但也比较容易理解

康拓展开就是对全排列排序,以此解决空间过大的问题

朴素算法

现在我们面对着这样一个问题:在特定情境下,我们需要为全排列数赋值,那我们怎么处理?

一种做法就是直接用Long Long存,但缺点显而易见:空间招架不住

另外一种做法是用map存。说实话我不知道有什么太大的问题,貌似是可以的。不过STL这种东西,能不用就不用 真香

康托展开

先上公式:

定义:

\(a[x]=位置x后的数字中,小于位置x上数字的个数\)

公式:

\(f=\sum_{i=1}^{n} a[i]*(n-i)!\)

公式比较抽象,但胜在美观

怎么去理解呢?我们用34152这个例子来理解

  1. 观察第一位"3":当第一位是"1","2"时,全排列数肯定比该数要小;当第一位时"3"时,排名先后位置;当第一位是"4","5"时:全排列数肯定比该数要大。那么a[1]=2;
  2. 观察第二位"4":接着上一次的结果继续讨论,由于首位是"3"未知的,所以首位确定为"3"。此时,如果第二位如果是"1","2",则排列数肯定比原数要小;如果是"4",则未知;如果是"5",则肯定大,因此a[2]=2
  3. 继续讨论下去,相同道理

结果:
\(f=2*4!+2*3!+0*2!+1*1!+0*0!=61\)

康托逆展开

顾名思义,康托展开解决的是用全排列数到排名,那么康托逆展开就用排名还原出全排列数

思考一下康托展开是怎么实现的,它有点类似于一个特殊进制数,每\(n\)位的意义是\(n!\),那么只要除回去即可

依旧以34152为例,康托值为61

  1. 用 61 / 4! = 2余13,说明 ,说明比首位小的数有2个,所以首位为3。
  2. 用 13 / 3! = 2余1,说明 ,说明在第二位之后小于第二位的数有2个,所以第二位为4。
  3. 用 1 / 2! = 0余1,说明 ,说明在第三位之后没有小于第三位的数,所以第三位为1。
  4. 用 1 / 1! = 1余0,说明 ,说明在第二位之后小于第四位的数有1个,所以第四位为5。

还原出来34152

事实上,做题过程中,还是康托展开用的多,康托逆展开实际用处并不是很大

代码

code:

思路简单,代码易写,懒得复制粘贴ˋ( ° ▽、° ) 

康拓展开

标签:公式   问题:   顺序   问题   先后   哈希   相同   说明   自然数   

原文地址:https://www.cnblogs.com/ticmis/p/13210752.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!