人的理解能力真的变化很大,之前看着很迷茫的东西先在看来简单不少(其实是以前太菜了*-*)
康托展开式——据说是用来构建时的空间压缩,其他的什么用途我还不知道,希望有菊苣告诉我
康拓展开式最简单的用途是求一个数在这个数的全排列中(从小到大)的第几个(最小的是第0个,这个在之后会解释,还会用到)
说的不是很清楚,我们还是来看例子吧比如要知道45321在由1,2,3,4,5组成的数的第几个计算如下
X=3*4!+3*3!+2*2!+1*1!+0*0!=95解释下这个式子吧。。。。。。。。。。。。
第一个数字是4,比4小的有3个:1,2,3,由1开始的数字有4!个一共就有3*4!个
第二个数字是5,比5小的有4个,但是4已经用过了所以只有1,2,3,由1为第二位的数(第一位已经考虑完了)有3!个;
接下来类似就能完成了,读者可以自己写一个数算算,也可以跟着代码理解下
我们将12345用上述方法计算得0所以最小是0开始的就可以解释了
int cantor(int a[],int n)//a数组是给出的数,n是元素个数 { int ans=0; for(int i=1;i<=n;i++) { int k=0;//统计有多少数比a[i]小 for(int j=i+1;j<=n;j++) if(a[i]>a[j]) k++; ans+=k*fac(n-i);//fac函数是计算阶乘的,这里就不写了 } return ans;}
逆康拓展开式就是康托展开式的逆运算。。。。给定元素要你计算第n个的排列是什么
我们还是用45321来解释。
要求1,2,3,4,5排列的第96个的数,由于是从0开始的,所以我们在计算前先-1;
96/(4!)=3------23有三个数比它小的数是4
23/(3!)=3------5有三个数比它小的数是4,但是由于4之前已经用过了,所以实际上这时第四大的数是5;
5/(2!)=2-------1有两个数比它小的数是3
1/(1!)=1有一个数比它小的数是2
最后以为只能是1了
int cantor_reverse(int k,int n,int b[])//a数组是给出的数,n是元素个数 { k--; int v[23];//记录数字的使用情况 memset(v,0,sizeof(v)); int ans=0; for(int i=1;i<=n;i++) { int m=k/fac(n-i); k%=fac(n-i); for(int j=1;j<=m;j++) { if(v[j]) //如果有比他小的数已经用过了 m++; } b[i]=m+1; v[m]=1; } }
总之麻打麻打达内..........加油吧!