(數論十一)康托展開與逆康托展開

2021-08-29 20:21:23 字數 1836 閱讀 5845

一.引出康托展開

​ 動態規劃題有一類分支叫狀壓dp,意思就是把狀態壓縮為乙個二進位制陣列,然後轉為十進位制數儲存。一般n的大小不會超過20,因為20個狀態的組合就有2^20,也就是1e6種可能。

​ 對於一些題目,緊緊利用狀態壓縮,會發現狀態的組合數遠遠超過1e6的範圍,那時候我們沒有辦法在1s內遍歷出來,或者大到根本連陣列都開不出來的時候,一般情況下就需要用到康托展開

​ 例如:對於乙個組合 1 2 3 4 5 6 7 8,a操作可以讓其轉變為8 7 6 5 4 3 2 1,b操作可以讓其轉變為4 1 2 3 6 7 8 5,c操作可以讓其轉變為1 7 2 4 5 3 6 8

​ 給出乙個初始組合和目標組合,問由初始到目標最少的變換步驟,若多種則選字典樹最小的那種?

​ 對於這種題,如果我們把1~8看作0~7,拿這8個數的當作乙個狀態來儲存,需76543210種狀態(且裡邊有些狀態根本就不可能出現,如11111111),這樣肯定是不可行的。

​ 如果我們利用狀態壓縮把它轉為2進製,0為000,1為001,2為010….7為111,那麼8個數連在一起共有24位,也就是需要2^24 = 16777216個狀態進行儲存,然後縮小了7倍,但是陣列依舊太大了

​ 這時候,我們需要考慮康托展開對狀態進行定義

二.關於康托展開

​ 和狀壓陣列不同,康托展開陣列a[i]代表的是該序列從第i位開始到最後一位,第i位的數排第幾(排名和i都是從0開始)

​ 舉個例子:3,5,4,1,2中:a[0] = 2,a[1] = 3, a[2] = 2,a[3] = 0, a[4] = 0

​ 那麼3 5 4 1 2的狀態值 = a[0]✖️4! + a[1]✖️3! + a[2]✖️2! + a[3]✖️1! + a[4]✖️0! = 70

​ 也就是說,康托展開能夠把狀態壓縮到極致(即像上邊那種沒有用過的諸如11111111等都被拋棄掉,只剩有用的狀態存在),即節省了空間也節省了時間。

三.關於康托逆展開

​ 我們在二中得到的70可以通過康托逆展開重新得到3,5,4,1,2,方法如下:

​ 70 / 4! = 2餘22,因此a[0] = 2;

​ 22 / 3! = 3餘4,因此a[1] = 3;

​ 4 / 2! = 2餘0,因此a[2] = 2;

​ 0 / 1! = 0餘0,因此a[3] = 0;

​ 0 / 0! = 0餘0,因此a[4] = 0;

​ 在1, 2 , 3, 4, 5中,第2大(從0開始算)的數是3

​ 在1, 2 , 4, 5中,第3大(從0開始算)的數是5

​ 在1, 2 , 4中,第2大(從0開始算)的數是4

​ 在1, 2中,第0大(從0開始算)的數是1,最後乙個數就是2

​ 因此就能得到序列3,5,4,1,2

​ 以上就是康托逆展開

四.**實現:

​ (1)康托展開實現**:

fact[10];	//fact[i]儲存i的階乘的值

//把陣列s合併為乙個狀態num, k代表陣列長度

void cantor (int s, ll &num, int k)

num += fact[k - i - 1] * cnt;

}}

(2)康托逆展開**:

fact[10];	//fact[i]儲存i的階乘的值

//把狀態值num轉回陣列s

bool book[10]; //判斷序列中下角標為i的數是否已經標記

void inv_cantor (int s, ll num, int k) }}

}

​ 理論就是這些~

如果有寫的不對或者不全面的地方 可通過主頁的****進行指正,謝謝

數學 數論 康托展開與逆康托展開

康托展開 可以理解為把乙個全排列對映到乙個數上面,因為全排列如果按照從小到大或者從大到小,肯定是有乙個確定的序列的。一般是從小到大的序列個數。我們就是要求出這個序列的位置。想法很簡答,就是求出前面比他小的個數就可以了。理解為乙個每位都是階乘進製的數轉化為10進製的數。思路如下 先準備求每一位的階乘,...

數學 數論 康托展開與逆康托展開

康托展開 可以理解為把乙個全排列對映到乙個數上面,因為全排列如果按照從小到大或者從大到小,肯定是有乙個確定的序列的。一般是從小到大的序列個數。我們就是要求出這個序列的位置。想法很簡答,就是求出前面比他小的個數就可以了。理解為乙個每位都是階乘進製的數轉化為10進製的數。思路如下 先準備求每一位的階乘,...

康托展開 康托逆展開

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 為當前未出現的...