康托展開是乙個全排列到乙個自然數的雙射,常用於構建雜湊表時的空間壓縮。 康托展開的實質是計算當前排列在所有由小到大全排列中的順序,因此是可逆的。
解決的問題型別:有一組元素,按字典序從小排到大,在所有的組合型別中,某個組合排第幾?(從0開始排,或者說比該組合小的組合個數有多少)
公式:康托展開值x = a[n-1]*(n-1)! + a[n-2]*(n-2)! + ...... + a[i]*i! + ......+ a[1]*1! + a[0]*0! ;
a[i]為整數,表示當前未出現的元素排第幾個(從0開始排,或者說比該元素小的元素個數)。
舉例說明,有 5個元素。按字典序排列,最小的排列組合是12345,最大的排列組合是54321,計算34152的康托展開值。n=5。
第一位是3,3在未出現的元素12345這5個元素中排第3,但是從0開始排,a[4]=2;
第二位是4,4在未出現的元素1245中排第3(3已經出現過了)從0開始排,a[3]=2;
第三位是1,1在未出現的元素125中排第1(3和4已經出現過了),從0開始排,a[2]=0;
第四位是5,在未出現的元素25中,比5小的元素有1個,a[1]=1;
第五位是2,在未出現的元素2中,比2小的元素有0個,a[0]=0;
x = a[4]*4! + a[3]*3! + a[2]*2! + a[1]*1! + a[0]*0!
x = 2*4! + 2*3! + 0*2! + 1*1! +0*0! = 61
按照正常人的邏輯,從0開始排,排到61,就是所謂的62。
逆康托展開:求在所有全排列中排在第x位的組合是什麼?
舉例說明,在的排列組合中,排在第62位的是多少?
62-1=61。n=5,從(n-1)的階乘(n-1)!開始除。
61 / 4! = 2......13,說明a[4]=2,在所有未出現的元素12345中比首位小的數有2個,顯然是3
13 / 3! = 2......1,說明a[3]=2,在所有未出現的元素1245中比第二位小的數有2個,顯然是4
1 / 2! = 0......1,說明a[2]=0,在所有未出現的元素125中比第三位小的數有0個,顯然是1
1 / 1!= 1......0,說明a[1]=1,在所有未出現的元素25中比第四位小的數有1個,顯然是5
最後乙個,a[0]=0,最後乙個就是2了
所以排列組合是34152。
記憶體限制:64mb 時間限制:1000ms
難度:3
現在有"abcdefghijkl」12個字元,將其所有的排列中按字典序排列,給出任意一種排列,說出這個排列在所有的排列中是第幾小的?
第一行有乙個整數n(0輸出乙個整數m,佔一行,m表示排列是第幾位;
3abcdefghijkl
hgebkflacdji
gfkedhjblcia
1302715242
260726926
ac**:
#include#include#include
#include
#include
#include
using
namespace
std;
int fact[13
];string
a,s;
void f()///
列印階乘表
int num(char
b)
for(int i=0;i)
if( b==s[i] )
return0;
}int
cantor()
return
res;
}int main()///
nyoj139,康托展開
return0;
}
記憶體限制:64mb 時間限制:3000ms
難度:3
現在有"abcdefghijkl」12個字元,將其按字典序排列,如果給出任意一種排列,我們能說出這個排列在所有的排列中是第幾小的。但是現在我們給出它是第幾小,需要你求出它所代表的序列.
第一行有乙個整數n(0輸出乙個序列,佔一行,代表著第m小的序列。
複製
31302715242
260726926
abcdefghijklhgebkflacdji
gfkedhjblcia
ac**:
#include#include#include
#include
#include
#include
using
namespace
std;
int fact[13
],x,y;
string
a,s;
void f()///
列印階乘表
void
cantor()
}int main()///
nyoj143,逆康托展開
return0;
}
康托展開 康托逆展開
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...