康托展開(有關全排列)


康托展開:已知一個排列,求這個排列在全排列中是第幾個

康托展開逆運算:已知在全排列中排第幾,求這個排列

 

康托展開表示的是當前排列在n個不同元素的全排列中的名次。比如213在這3個數所有排列中排第3。

那么,對於n個數的排列,康托展開為:

其中表示第i個元素在未出現的元素(即 第i位~第n位的數字中,也就是求后面有幾個數字比ai小)中排列第幾。舉個簡單的例子:

對於排列4213來說,4在4213中排第3,注意從0開始,2在213中排第1,1在13中排第0,3在3中排第0,即:

,這樣得到4213在所有排列中排第ans=20

代碼實現:(從0開始計數)

//康托展開  
LL Work(char str[])  
{  
    int len = strlen(str);  
    LL ans = 0;  
    for(int i=0; i<len; i++)  
    {  
        int tmp = 0;  
        for(int j=i+1; j<len; j++)  
            if(str[j] < str[i]) tmp++;  
        ans += tmp * f[len-i-1];  //f[]為階乘  
    }  
    return ans;  //返回該字符串是全排列中第幾大,從1開始  
}  

康托展開的逆運算:就是根據某個排列的在總的排列中的名次來確定這個排列。比如:

求1234所有排列中排第20的是啥,那么就利用輾轉相除法確定康托展開中的系數,然后每次輸出當前未出現過的第個元素。

代碼實現康托展開逆運算:

//康托展開逆運算  
void Work(LL n,LL m)  
{  
    n--;  
    vector<int> v;  
    vector<int> a;  
    for(int i=1;i<=m;i++)  
        v.push_back(i);  
    for(int i=m;i>=1;i--)  
    {  
        LL r = n % f[i-1];  
        LL t = n / f[i-1];  
        n = r;  
        sort(v.begin(),v.end());  
        a.push_back(v[t]);  
        v.erase(v.begin()+t);  
    }  
    vector<int>::iterator it;  
    for(it = a.begin();it != a.end();it++)  
        cout<<*it;  
    cout<<endl;  
}  

全部來自:http://blog.csdn.net/acdreamers/article/details/7982067

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM