nyoj 139 143 康托展開與逆展開

2021-07-15 18:03:25 字數 2089 閱讀 4765

139題用的是康托展開:

x=a[n](n-1)!+a[n-1](n-2)!+…+a[i]*(i-1)!+…+a[1]*0! 其中a[i]為當前未出現的元素中是排在第幾個(從0開始)。 //假設序列是a[n],a[n-1],a[n-1]……a[1]

如 按從小到大排列一共6個。123 132 213 231 312 321 。

如求321是中第幾個大的數可以這樣考慮 :

第一位是3,當第一位的數小於3時,那排列數小於321 如 123、 213 ,小於3的數有1、2 。所以有2*2!個。再看小於第二位2的:小於2的數只有乙個就是1 ,所以有1*1!=1 所以小於321的排列數有2*2!+1*1!=5個。所以321是第6個大的數。 2*2!+1*1!+1*0!

再舉個例子:

1324是排列數中第幾個大的數:第一位是1小於1的數沒有,是0個 0*3! 第二位是3小於3的數有1和2,但1已經在第一位了,所以只有乙個數2 1*2! 。第三位是2小於2的數是1,但1在第一位,所以有0個數 0*1! ,所以比1324小的排列有0*3!+1*2!+0*1!=2個,1324是第三個大數。

**:

#include 

using namespace std;

int main()

int n,count,length;

long

long

sum;

string x;

cin>>n;

while(n--)

sum+=count*a[length-i-1]; //+=count*(length-i-1)!

}cout<0;}

143題呢,是逆推的,由第幾個,求得該序列

如果已知 s = [「a」, 「b」, 「c」, 「d」],x(s1) = 20,能否推出 s1 = [「d」, 「b」, 「a」, 「c」] 呢?

因為已知 x(s1) = a4*3! + a3*2! + a2*1! + a1*0! = 20,所以問題變成由 20 能否唯一地對映出一組 a4、a3、a2、a1?如果不考慮 ai 的取值範圍,有

3*3! + 1*2! + 0*1! + 0*0! = 20

2*3! + 4*2! + 0*1! + 0*0! = 20

1*3! + 7*2! + 0*1! + 0*0! = 20

0*3! + 10*2! + 0*1! + 0*0! = 20

0*3! + 0*2! + 20*1! + 0*0! = 20

等等。但是滿足 0 <= ai <= n-1 的只有第一組。可以使用輾轉相除的方法得到 ai,即:

20/(3!)=3餘2 //a4=3

2/(2!) =1餘0 //a3=1

0/(1!) =0餘0 //a2=0

0/(0!) =0餘0 //a1=0

知道了a4、a3、a2、a1的值,就可以知道s1[0] 是子陣列[「a」, 「b」, 「c」, 「d」]中第3大的元素 「d」,s1[1] 是子陣列 [「a」, 「b」, 「c」] 中第1大的元素」b」,s1[2] 是子陣列 [「a」, 「c」] 中第0大的元素」a」,s[3] 是子陣列 [「c」] 中第0大的元素」c」,所以s1 = [「d」, 「b」, 「a」, 「c」]。

再例如:

的全排列,並且已經從小到大排序完畢

找第96個數

首先用96-1得到95

用95去除4! 得到3餘23

有3個數比它小的數是4

所以第一位是4

用23去除3! 得到3餘5

有3個數比它小的數是4但4已經在之前出現過了所以第二位是5(4在之前出現過,所以實際比5小的數是3個)

用5去除2!得到2餘1

有2個數比它小的數是3,第三位是3

用1去除1!得到1餘0

有1個數比它小的數是2,第二位是2

最後乙個數只能是1

所以這個數是45321

**:

#include 

#include

using

namespace

std;

int main()

cout

0;}

康托展開與康托逆展開

康托展開,用人話說出來.就是把乙個陣列的多種排序情況對應用數字表示出來 公式 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 分別為第乙個和最後乙個排列。康托展開公式為...

康托展開與康托逆展開

舉例,對於 1 4 的乙個全排列 1,2,3,4 和 4,3,2,1 我們知道,按字典序,前者是該全排列集合的第乙個,後者是該集合的最後乙個。那麼,所謂康托展開,就是給定乙個 n 位數的全排列,我們可以根據康托展開公式確定其應當是字典序中的第 幾 個全排列。康托展開計算的就是某個全排列在該全排列集合...