時間限制:1000 ms | 記憶體限制:65535 kb
難度:3
描述 現在有"abcdefghijkl」12個字元,將其所有的排列中按字典序排列,給出任意一種排列,說出這個排列在所有的排列中是第幾小的?
輸入第一行有乙個整數n(0
輸出輸出乙個整數m,佔一行,m表示排列是第幾位;
樣例輸入2
abcdefghijkl
hgebkflacdji
樣例輸出1
302715242
解析:
這道題是給出一串字母,求按字典序中的排序。
演算法:康托展開
康托展開就是一種特殊的雜湊函式,它的使用範圍是對於n個數的排列進行狀態的壓縮和儲存,是乙個
全排列到乙個
自然數的
雙射,常用於構建
雜湊表時的空間壓縮。 康托展開的實質是計算當前排列在所有由小到大全排列中的順序,因此是可逆的。
以下稱第x個全排列是都是指由小到大的順序。
x=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0!
其中,a[i]為整數,並且0<=a[i]
a[i]的意義參見舉例中的解釋部分
例如,3 5 7 4 1 2 9 6 8 展開為 98884。因為x=2*8!+3*7!+4*6!+2*5!+0*4!+0*3!+2*2!+0*1!+0*0!=98884.
解釋:排列的第一位是3,比3小的數有兩個,以這樣的數開始的排列有8!個,因此第一項為2*8!
排列的第二位是5,比5小的數有1、2、3、4,由於3已經出現,因此共有3個比5小的數,這樣的排列有7!個,因此第二項為3*7!
以此類推,直至0*0!
顯然,n位(0~n-1)全排列後,其康托展開唯一且最大約為n!,因此可以由更小的空間來儲存這些排列。由公式可將x逆推出對應的全排列。
既然康托展開是乙個雙射,那麼一定可以通過康托展開值求出原排列,即可以求出n的全排列中第x大排列。
如n=5,x=96時:
首先用96-1得到95,說明x之前有95個排列.(將此數本身減去!)用95去除4! 得到3餘23,說明有3個數比第1位小,所以第一位是4.
用23去除3! 得到3餘5,說明有3個數比第2位小,所以是4,但是4已出現過,因此是5.
用5去除2!得到2餘1,類似地,這一位是3.
用1去除1!得到1餘0,這一位是2.
最後一位只能是1.
所以這個數是45321.
**:139題
#include
#include
int main()
printf("%lld\n",++num);
}}
143題
**:#include
#include
int main()
for(i=0;i<12;i++)
printf("%c",c[i]+97);
printf("\n");
}return 0;}
nyoj 139 我排第幾個(康托展開)
時間限制 1000 ms 記憶體限制 65535 kb 難度 3 描述 現在有 abcdefghijkl 12個字元,將其所有的排列中按字典序排列,給出任意一種排列,說出這個排列在所有的排列中是第幾小的?輸入 第一行有乙個整數n 0 輸出輸出乙個整數m,佔一行,m表示排列是第幾位 樣例輸入 3 ab...
nyoj139 我排第幾個(康拓展開)
時間限制 1000 ms 記憶體限制 65535 kb 難度 3描述 現在有 abcdefghijkl 12個字元,將其所有的排列中按字典序排列,給出任意一種排列,說出這個排列在所有的排列中是第幾小的?輸入 第一行有乙個整數n 0 輸出輸出乙個整數m,佔一行,m表示排列是第幾位 樣例輸入 3 abc...
NYOJ 139 我排第幾個(康托展開)
時間限制 1000 ms 記憶體限制 65535 kb 難度 3 描述現在有 abcdefghijkl 12個字元,將其所有的排列中按字典序排列,給出任意一種排列,說出這個排列在所有的排列中是第幾小的?輸入第一行有乙個整數n 0 輸出輸出乙個整數m,佔一行,m表示排列是第幾位 樣例輸入 3 abcd...