康托展開
可以理解為把乙個全排列對映到乙個數上面,因為全排列如果按照從小到大或者從大到小,肯定是有乙個確定的序列的。
一般是從小到大的序列個數。我們就是要求出這個序列的位置。,想法很簡答,就是求出前面比他小的個數就可以了。
理解為乙個每位都是階乘進製的數轉化為10進製的數。思路如下:
先準備求每一位的階乘,然後從高位開始統計後面有多少個數比他小記錄這個個位數,然後乘以後面個數的階乘,再把它累加起來。
x[i]表示第i位後面比他小的個數,那麼
∑ 1n
x[i]
∗fac
[n−i
]\sum_^x[i]*fac[n-i]
1∑nx[
i]∗f
ac[n
−i]這樣就能求出比他小的有多少個了,也能求出他是第幾個序列。
//求出階乘
void
init()
}int
kangtuo
(int n,
char a)
return sum+1;
}
逆康托展開
相當於知道序列位置求這個位置的數。
想法也很簡單,因為對於每位的fac[n-i]都比後面說有的和都大,所以用pos/fac[n-1]求得的就是x[i],同理pos%fac[n-i]就是後面的和。
我們維護乙個序列st始終按照從小到大排列,那麼已知某位置的x[i],那麼這個位置的數就是st[x[i]+1]。
void
init()
}void
reverse_kangtuo
(int n,
int k,
char s)
;--k;
for(i=
0; i) s[i]
='0'
+j; vst[j]=1
; k %
= fac[n-i-1]
;}}
數學 數論 康托展開與逆康托展開
康托展開 可以理解為把乙個全排列對映到乙個數上面,因為全排列如果按照從小到大或者從大到小,肯定是有乙個確定的序列的。一般是從小到大的序列個數。我們就是要求出這個序列的位置。想法很簡答,就是求出前面比他小的個數就可以了。理解為乙個每位都是階乘進製的數轉化為10進製的數。思路如下 先準備求每一位的階乘,...
數學 康托展開 康托逆展開
7.15 康托展開,就是把全排列轉化為唯一對應自然數的演算法。它可以建立1 n的全排列與 1,n 之間的自然數的雙向對映。1 康托展開 儘管我並不清楚康托展開的原理何在,這個演算法的過程還是比較好記的。正確性之後有機會詢問下學長。如果從1開始給全排列的排名從大到小編號的話 從0開始也可,建立的是與 ...
(數論十一)康托展開與逆康托展開
一.引出康托展開 動態規劃題有一類分支叫狀壓dp,意思就是把狀態壓縮為乙個二進位制陣列,然後轉為十進位制數儲存。一般n的大小不會超過20,因為20個狀態的組合就有2 20,也就是1e6種可能。對於一些題目,緊緊利用狀態壓縮,會發現狀態的組合數遠遠超過1e6的範圍,那時候我們沒有辦法在1s內遍歷出來,...