浅谈康托展开与其逆.
康托展开
What's this?
来自度娘的解释:
康托展开是一个全排列到一个自然数的双射,常用于构建哈希表时的空间压缩。 康托展开的实质是计算当前排列在所有由小到大全排列中的顺序,因此是可逆的。
概念应该不是很好理解,所以这里直接给出作用.
这里的解释与网络上的不同,但是做题的时候是对的,这里请大家不要喷 qwq
Function
康托展开的作用是求n个数的全排列中某一个序列在所有排列中的次序(该排列次序(亦称之为排名)以字典序从小到大排序)
栗子
不理解的话还是来看下栗子好了.
Q:求在的全排列中的排第几位.
A: 这很简单,我们可以写出的全排列再去看排名
很容易看出的排名为第二名.
不理解的话还是自己手跑大样例.如果你不嫌累的话
这样写是为了自己好写,好理解些.
注意:康托展开应该是从排名为开始计数的。
深入
如果说,给我们的很大怎么办?
这时候就用到了康托展开.
考虑到的全排列会有种,很明显,我们需要用到阶乘.
这里可能会有些解释不清楚.请大家见谅。
我们对于某一个排列,其排名肯定会与后边的排列有关。
即的排名会与有关,而又会与相关......
所以这里会用到阶乘
这里给出公式:
定义:
- 代表当前排列的排名。
- 代表当前排列里从位置向右比位置的数小的数的个数.
栗子:在的全排列中,计算的康托展开值。
首位是,我们用眼睛观察发现后面比小的数有两个.则
第二位是,发现后面比小的数有两个,注意这里是没有贡献的,它在的前面,则
第三位是,后面没有比小的数,则
第四位是,同样,后面比小的数只有则
第五位是,后面没有数了则
因此我们可以算出
所以从零开始计数的话我们算出的的排名为
从一开始计数的话我们算出的排名则要为
这里的话,与网上的有些不同,这里通过公式直接求出来的就是排名.不过这个排名和网络上的其他讲解不太相同。
这里还有度娘的讲解.不过和我的理解不太一样.
代码
int Contor(char s[],int n)
{
int ans=0;
for(R int i=0;i<n;i++)
{
int smaller=0;
for(R int j= i+1 ;j<n;j++)
{
if(s[i] > s[j])smaller++;
}
ans += smaller*fac[n-i-1];
}
return ans+1;
}
逆康托展开
What?
什么?这玩意还能逆推?
当然.我们既然知道了这种式子,就肯定能倒推出来原排列啊 emm.
由于康托展开是一个双射.我不知道是啥
所以我们可以逆推回来
栗子
在的全排列中,给出,我们可求
这里给出的排名一般是从开始计算的.
这里给出求解过程
用 余,说明,说明比第一位数小的数有个,所以第一位填。
用 余,说明,说明在第二位后面小于第二位的数有个,所以第二位为。
用 余,说明,说明在第三位后面没有小于第三位的数,所以第三位为。
用 余,说明,说明在第二位之后小于第四位的数有个,所以第四位为。
最后一位就是剩下的啦。
通过以上分析,所求排列为。
式子的话,先除后模就好了
代码
void DeCantor(int x,int n)
{
memset(use,0,sizeof use);
x--;//这里从0开始计数,因此--.
int j;
for(R int i=1;i<=n;i++)
{
int t=x/fac[n-i] ;//求后面有几位比当前位小
for(j=1;j<=n;j++)
{
if(!use[j])
{
if(!t)break;
t--;
}
}
printf("%d ",j);
vis[j]=1;
x%=fac[n-i];
}
}
应用的话,见提高组第四题
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Linux系统下SQL Server数据库镜像配置全流程详解
· 现代计算机视觉入门之:什么是视频
· 你所不知道的 C/C++ 宏知识
· 不到万不得已,千万不要去外包
· C# WebAPI 插件热插拔(持续更新中)
· 会议真的有必要吗?我们产品开发9年了,但从来没开过会
· 【译】我们最喜欢的2024年的 Visual Studio 新功能
· 如何打造一个高并发系统?