康托展開用來求陣列是該全排列的第幾項,康托展開的逆運用用於求全排列的第幾個排列。
已知對於1-n個數的全排列,總共的可能是n!種。對於乙個已知的數列比如45321,在第一項是4時,表示第一項在此之前已經填放過1 2 3了,而後面的第二項至第五項則又是乙個全排列,那麼此時的排列數就是3 * 4 !;第二位是5,則在放入5之前第二項已經放過1 2 3了,那麼排列數再加上3 * 3!;依次類推,最終答案為:∑n
i=1=
a[i]
∗(n−
i)!其中a[i]表示第i項前比它小的沒出現過的數字的個數。
易證,a[
1]∗(
n−1)
!>∑n
i=2=
a[i]
∗(n−
i)!,因此給定乙個r表示是全排列的第r項,由r/
(n−1
)!得到a[1],則第一位數即a[1] + 1;在r中減去(a[1] + 1) * (n -1)!,同理可以由$r / (n-2)!&得到a[2];依次類推,最後得到整個排列。
要注意的是 0! = 1
**模版:
ll fac[20]; //階乘
void getfac()
ll cantor(int *a,int
len) //康托展開求a是全排列第幾項,a從1開始
; for(int i=1;i<=len
-1;i++)
return ret +1;
}void _cantor(ll r,int
len) //康托展開逆運算求第r個排列
,a[20];
for(int i=1;i<=len;i++)
vis[j] =1;
a[i] = j;
}for(int i=1;iprintf("%d ",a[i]);
printf("%d\n",a[len]);
}
康托展開及其逆運算
康托展開的wiki介紹 申明 1.用c語言實現。2.for中的i,j定義適用於c99標準,gcc編譯要新增 std c99選項。或者將i,j的定義放到for之前的外部作用域。3.逆運算使用了c99標準的vla,即變長陣列,只能用於區域性作用域,且宣告時不能初始化 也可以不用vla,使用malloc等...
康托展開與康托逆展開
康托展開,用人話說出來.就是把乙個陣列的多種排序情況對應用數字表示出來 公式 x a i n 1 a i 1 n 2 a 1 0 其中a i 表示後面比該元素小的元素的個數 舉個例子,有5個數1 2 3 4 5 共有5個元素,所以一共有5!種排序方法 如果用康托展開序列35142 第乙個元素是3,在...
康托展開與逆康托展開
1.康托展開 康托展開是乙個全排列到乙個自然數的雙射,常用於構建hash表時的空間壓縮。設有n個數 1,2,3,4,n 可以有組成不同 n 種 的排列組合,康托展開表示的就是是當前排列組合 例如對於 1 4 的乙個全排列,1,2,3,4 和 4,3,2,1 分別為第乙個和最後乙個排列。康托展開公式為...