星星之火OIer:康拓&逆康拓展开

仅仅只是为了自己的另一篇博客水了一份

概念

康托展开是指一个全排列到一个自然数的双射,因为全排列是不重复的,所以也有逆康拓展开

Example

在八数码问题中,如果想法简单一点,直接用数组987654321来开,就算是bool类型也会爆

但是用康托展开映射后,最大只需要开到9!=362880,空间复杂度降低了不少

如何实现

康拓

令x为康托展开后的对应值

x=A[0]*(n-1)!+A[1]*(n-2)!+\cdots +A[n-1]*0!

这里的A[i]表示在i后面还有几个比它本身小的值

注意,此处计算出来的x应为从0开始排的结果,如果习惯从1开始则还要+1

Example

对于数列\begin{bmatrix} 3 & 1 & 4 & 2 & 5 \end{bmatrix}

我们用康托展开试一下

x=2*4!+0*3!+1*2!+0*1!+0*0!=50

所以这个数列应该是全排的第51个

大家可以手推一下,也可以把数据换小一点验证

逆康拓

还是用刚刚那个数据

康拓返回值是50

具体过程如下

  • 50\div 4!=2\cdots \cdots 2,说明比第一位小的有2个,所以第一位是3
  • 2\div 3!=0\cdots \cdots 2,说明第二位以后比第二位小的有0个,所以第二位是1
  • 2\div 2!=1\cdots \cdots 0,说明第三位以后比第三位小的有1个,所以第三位是4
  • 0\div1!=0\cdots \cdots 0,说明第四位以后比第四位小的有0个,所以第四位是2
  • 最后一个理所当然是5
  • 综上,数列为\begin{bmatrix} 3 &1 &4 &2 &5 \end{bmatrix}

代码

il it cantor(ch s[]) {
	memset(flag,1,sizeof(flag));
	it ans=0,temp;
	for(it i=0;i<9;i++) {
		flag[s[i]-'0']=0;//已经扫过,后面就不必再计算了
		temp=0;
		for(it j=0;j

逆康拓展开因为这道题里不需要,作者就偷一个懒,请大家自己想好辣

你可能感兴趣的:(辅助,数论)