數學基礎 康托展開介紹

2021-08-21 20:38:55 字數 1449 閱讀 3609

有乙個以元素為排列元素的全排列

1.給定乙個全排列序列,求該序列是所有全排列序列中字典序第幾的序列

2.(逆用)給定全排列大小n,字典序k,求字典序為k的排列

1.獲取排列的id,構建hash表

2.計算關於排列序列的問題(如:noip普及組2004火星人)

3.etc.

(想要更好的理解下面的講解,請保證你已經學習了關於排列組合的基本知識)

用法1:

例如:給定n=4,序列:3214,求該排列字典序

解法一:

首先1234的字典序為1,1243字典序為2,以此類推

a.所以我們可以用c++stl中的next_permutation函式(下乙個排列函式)來暴力從1234開始不斷求下乙個排列,直到達到目標狀態

b.我們還可以對3214用pre_permutation(前乙個排列函式)

解法二(康托展開):

第一位為3,則當第一位為1,2時生成的排列比目標排列小,有所以2*3!種;

第二位為2,當第二位為1是生成的排列更小,有1*2!種;

第三位為1,沒有比1更小的排列方法,有0*1!種

第四位為4,由於1,2,3,在前面已經使用了,使用沒有比4更小的了,有0*0!種

使用總共有2*3!+1*2!+0*1!+0*0!=14種排列方法比目標排列字典序小,則目標排列字典序為15(不要忘記加一)

公式:

其中k[i]表示對於第i位的a[i],a[i+1]到a[n]種比a[i]小的數字的個數

**實現:

cin>>n;

fac[0]=1;

for(int i=1;i<=n;i++)//預處理階乘

fac[i]=fac[i-1]*i;

int ans=1;//注意

for(int i=1;i<=n;i++) cin>>a[i];

for(int i=1;i<=n;i++)

a[i]=j;

vis[j]=true;

} for(int i=1;i<=n;i++) cout<

數學 康托展開 康托逆展開

7.15 康托展開,就是把全排列轉化為唯一對應自然數的演算法。它可以建立1 n的全排列與 1,n 之間的自然數的雙向對映。1 康托展開 儘管我並不清楚康托展開的原理何在,這個演算法的過程還是比較好記的。正確性之後有機會詢問下學長。如果從1開始給全排列的排名從大到小編號的話 從0開始也可,建立的是與 ...

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

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

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

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