數學 康托展開 康托逆展開

2022-05-25 16:00:17 字數 1423 閱讀 2479

(7.15)康托展開,就是把全排列轉化為唯一對應自然數的演算法。它可以建立1 ~ n的全排列與[1, n!]之間的自然數的雙向對映。

1、康托展開:

儘管我並不清楚康托展開的原理何在,這個演算法的過程還是比較好記的。正確性之後有機會詢問下學長。

如果從1開始給全排列的排名從大到小編號的話(從0開始也可,建立的是與[0, n!-1]的對映,本質相同),定義rk為排名,a是排列陣列,排列有n位(最低位是第0位),那麼有公式

rk - 1 = cnt[n-1] * (n-1)! + cnt[n-2] * (n-2)! + ... + cnt[0] * 0!  

其中cnt陣列的含義是未統計的數字中,小於a[i]的數字有多少個。

舉例:計算排列3 4 2 1對於的排名

首先取出最高位(第三位),小於數字3的數有兩個,所以cnt[3] = 2,rk += 2 * 3!,rk = 12。

然後取出4,小於4的數有三個,但是3已經被統計過了,所以cnt[2] = 2,rk += 2 * 2!,rk = 16.

取出2,小於2的只有1,cnt[1] = 1,rk += 1 * 1!,rk = 17。

最後由於除第0位本身外已經沒有數了,cnt[0]恆等於0。所以3 4 2 1的排名為18。

**:#include 

#include 

#include 

using namespace std;    

int f[10], n;    

bool vis[10];    

int ktsplay(int *a)     

return rk + 1;    

}    

int a[10];    

int main()     

(先咕掉逆展開)

(先補一點)

康托展開的逆過程,就是依照排名來查詢排列。

首先把排名-1(突然發現這樣有點麻煩,可能從0開始編排名號更合理,大家看得懂就好)。然後我們考慮康托展開的過程,用帶餘除法的方式確定每一位數字的排名,進而得到這個數。

比如我們要計算排列中排第18的排列。

第三位(最高位):17/3! = 2……5,說明比該位小的數有2個,該位是3。

第二位:5/2! = 2……1,說明這一位是當前沒出現的第2個,該位是4。

第三位:1/1! = 1……0,說明這一位是2。

那麼最後一位是1。

所以所求排列是3、4、2、1。

**:void ktresplay(int rk)   

vis[j] = true;  

a[i] = j;  

rk = rk % f[i];  

}  for (int i = 1; i <= n; ++i)  

if (!vis[i])   

return;  

}  (2019.7.16 坑填了)

康托展開 康托逆展開

x a n n 1 a n 1 n 2 a i i 1 a 1 0 其中a i 為當前未出現的元素中是排在第幾個 從0開始 這就是康托展開。康托展開可用 實現。編輯 把乙個整數x展開成如下形式 x a n n 1 a n 1 n 2 a i i 1 a 2 1 a 1 0 其中a i 為當前未出現的...

康托展開 逆康托展開

康托展開 問題 給定的全排列,計算出它是第幾個排列 求序列號 方法 康托展開 對於乙個長度為 n 的排列 num 1 n 其序列號 x 為 x a 1 n i a 2 n 2 a i n i a n 1 1 a n 0 其中a i 表示在num i 1 n 中比num i 小的數的數量 includ...

康托展開 逆康托展開

用途 康托展開是一種雙射,用於排列和整數之間的對映,可用於排列的雜湊 康托展開 公式 i n1pi i 1 sum limits p i i 1 i n 1 pi i 1 其中p ip i pi 為第i ii個數構成的逆序的個數,n為排列數的個數 例 排列 2134 i n1pi i 1 sum l...