問題:
給你一些不重複的元素,
將它們從小到大排序,
問你某個排列在所有的排列處於第幾大;
康拓展開:公式為:x=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0!(an是n這個數字在所有元素中排第幾從0開始算,也就是有幾個比n小的數字)
講解:
舉個例子現在有4個元素為1,2,3,4,將他們從小到大排序結果如下:
①1 2 3 4 ⑦
2 1 3 4
⑬3 1 2 4
⑲4 1 2 3
②1 2 4 3 ⑧
2 1 4 3
⑭3 1 4 2
⑳4 1 3 2
③1 3 2 4 ⑨2 3 1 4
⑮3 2 1 4 ㉑4 2 1 3
④1 3 4 2 ⑩2 3 4 1
⑯3 2 4 1 ㉒4 2 3 1
⑤1 4 2 3 ⑪
2 4 1 3
⑰3 4 1 2 ㉓4 3 1 2
⑥1 4 3 2
⑫2 4 3 1
⑱3 4 2 1 ㉔4 3 2 1
現在問你4 2 1 3在這中序列中排第幾位,大家是對照著上面的一眼就看出來了,如果沒有這個表呢,如果數字再多幾位呢,是不是感覺很難找到他的我位置了,而康拓展開只需要通過一些計算就可以算出來他的位置,而不需要排列出這些元素再去尋找;公式在上面;現在說一下為什麼是這樣呢;
就比如4
2 1
3這個序列
先看第一位4,比4小的數字有三個1,2,3,所以,以這三個數字開頭的排列均小於它,3*(
4-1)!為18,
(這一步中比4開頭小的有1,2,3,以這三個數字開頭,不論後面三個數字怎麼排都不會大於它,這就是(4-1)!)
再看第二位2,比2小的數字有一位1,所以,從第二位開始以1開頭的排列均小於它,1*(4-1-1)!為2,
(在4排在第一時(即第一步的情況下),這一步中比2開頭的數字有乙個1,以4 1的順序排,不論後面怎麼排都不會大於它,即(4-1-1)!)
再看第三位1,比1小的數字有零個,所以,0*(4-2-1)!為0,
再看第四位4,比3小的數字有兩個1,2然而1,2都排好了所以比三小的數字為零,所以,0*(4-3-1)為0;
x=3*(
4-1)+1*(4-1-1)!+
0*(4-2-1)!+
0*(4-3-1)!=20;
在它前面有20個比他小的,所以他就排在20+1的位置;
看到這應該對康拓展開差不多理解了把,那麼**該怎麼寫呢?
long long kt(string a)
{ long long sum=0,cnt,len=a.length();//sum為第幾大,cnt為乙個臨時變數求比當前這個數字小的還有幾個,len就是長度
for(int i=0;i
這有一道模板題大家可以看看,
nwsoj1235
:我排第幾個(我部落格有題解需要自找)
康拓展開和逆康拓展開
康托展開就是一種特殊的雜湊函式 把乙個整數x展開成如下形式 x a n n a n 1 n 1 a 2 2 a 1 1 其中,a為整數,並且0 a表示1,2,3,n的排列如 按從小到大排列一共6種,就是123 132 213 231 312 321 代表的數字 1 2 3 4 5 6 也就是把10進...
康拓展開與逆康拓展開
首先解釋一下,所謂的康拓展開,就是能夠通過乙個式子,得到乙個排列在所有排列中的按字典序排好後的位次。而逆康托展開,則是給出排列的位次,能夠計算出排列是什麼。下面先給出康拓展開的公式 其中ai 為整數,並且 0 ai ai表示原數的第 i位在當前未出現的元素中是排在第幾個 康拓展開是乙個雙射,因此常用...
康拓展開和逆康拓展開
康拓展開模板題 複雜度o n 2 的會tle 看資料就知道了 雖然某題解說可以,不知道是不是後期加強了資料 然而我還是寫了o n 2 的 include typedef long long ll ll f 1000010 const ll mod 998244353 int a 1000010 b ...