zoukankan      html  css  js  c++  java
  • 全排列的编码与解码——康托展开

    康托展开是一个全排列到一个自然数的映射,可以快速求出一个全排列在所有全排列中字典序排第几

    康托展开公式

    $Large X=a_n*(n-1)!+a_{n-1}*(n-2)!+……+a_1*0!$

    其中$a_i$表示全排列中后i个元素,第n-i+1个元素排第几(然后要减一)

    证明

    $a_i*(i-1)!$表示所有全排列中前n-i个元素与当前全排列相同,且第n-i+1个元素比当前全排列小的所有全排列都比当前全排列小

    这样所有数相加就代表比当前全排列小的全排列的个数

    代码实现

    const int fac[]={1, 1, 2, 6, 24, 120, 720, 5040, 40320};//阶乘,不够用可以再加 
    int cantor(int a[],int k){//康托展开 
        int ans=0,tmp;
        for(int i=0;i<k;i++){
            tmp=0;//记录有几个比它小的数 
            for(int j=i+1;j<k;j++){
                if(a[j]<a[i])tmp++;
            }
            ans+=tmp*fac[k-i-1];
        }
        return ans;
    }
    void uncantor(int a[],int k,int num){//逆康托展开
        int b[10];//b表示剩下的数,并且按升序排列 
        for(int i=0;i<k;i++)b[i]=i+1;
        b[k]=0;
        for(int i=0,x;i<k;i++){
            x=num/fac[k-i-1],num%=fac[k-i-1],a[i]=b[x];//x表示当前数是剩下的数中的第几个 
            for(int j=x;b[j];j++){
                b[j]=b[j+1];
            }
        }
    }
  • 相关阅读:
    读《暗时间》
    文献笔记8
    文献笔记4
    文献笔记2
    文献笔记5
    文献笔记6
    文献笔记1
    文献笔记3
    读《暗时间》2
    文献笔记7
  • 原文地址:https://www.cnblogs.com/bennettz/p/8286590.html
Copyright © 2011-2022 走看看