模板

康托展开和逆康托展开是一个全排列到一个自然数的双射。\(n\)个数有\(n!\)种全排列,康托展开表示的是当前的排列在所有全排列中,按照字典序排位的顺序。
康托展开可以用来构建哈希表,压缩空间。
计算方法:

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

其中\(a[i]\)表示在从第一个元素到第\(i-1\)个元素的所有未出现的元素中,小于元素i的元素个数。
比如对于三个元素\(\{ 1,2,3\}\)

排列 康托展开 位次
1 2 3 \(0*2!+0*1!+0*0!=0\) 1
1 3 2 \(0*2!+1*1!+0*0!=1\) 2
2 1 3 \(1*2!+0*1!+0*0!=2\) 3
2 3 1 \(1*2!+1*1!+0*0!=3\) 4
3 1 2 \(2*2!+0*1!+0*0!=4\) 5
3 2 1 \(2*2!+1*1!+0*0!=5\) 6
康托展开可以通过两重循环实现,时间复杂度\(O(n^2)\),也可以使用线段树等数据结构优化。
int cantor(char* a,int n){
    int cnt,hash=0;
    for(int i=0;i<n;i++){
        cnt=0;
        for(int j=i+1;j<n;j++){
            if(a[j]<a[i]) cnt++;
        }
        hash+=cnt*fac[n-i-1];
    }
    return hash;
}
posted @ 2020-07-20 16:09  fxq1304  阅读(107)  评论(0编辑  收藏  举报