排列的編碼 康托展開

2021-08-21 07:43:14 字數 3326 閱讀 7443

題目大意:

15,67
思路:

考試時居然把這道題推出來了。。。

然後還ak了。。。

正題:這道題要我們求出這個排列是字典序第幾大的,也就是讓我們求有多少個排列比該排列小,再加1即是答案。

那麼應該如何考慮呢?

舉個例子

這個排列是

考慮萬位數,有多少個數只填萬位數就肯定比它小呢?

很明顯,如果必須比它小,那麼就只有萬位數為

1 1

或2' role="presentation">2

2才行。那麼萬位數為

1 1

或2' role="presentation">2

2的又有幾個數呢?

如果把數字

1 1

放入萬位

無論後面放入什麼數字,都滿足這個數字小於

35124

' role="presentation">35124

35124

所以說,後面的數字可以隨便填,方案數為4!4!

(! !

表示階乘,後面相同)

那麼把2

' role="presentation">2

2填進萬位也有4!

4

!種方法,所以僅看萬位就有2×

4!=48

2 ×4

!=48種填法。

那麼接下來看千位

填千位使得這個數必然小於35

124 351

24一共有幾種方案呢?

按照原來的方法,應該有4×

3!=24

4 ×3

!=24種方法。

但是,這樣錯了!

我們來把這個過程模擬一遍。

這個數千位必須小於5,那麼就有

1 1

,2' role="presentation">22,

3 3

,4' role="presentation">4

4四個數可填。

但是!

我們在填萬位數的時候就已經把

1 1

或2' role="presentation">2

2填進去了,所以如果萬位填

1 1

,那麼千位就不能填

1' role="presentation">1

1(每個數只能填一遍),那就只有

2 2

,3' role="presentation">33,

4 4

三個數可填。同理,如果將

2' role="presentation">2

2填入萬位,就只有

1 1

,2' role="presentation">22,

3 3

三個數可填。

所以無論用哪種填法,千位都只能填3個數!

但是如果這個樣例是這樣的

(真有趣)

那麼總共就是48+

18+0+

0+0=

66 48+18

+0+0

+0=66

個數字比35

124 351

24小。 那麼3

5124

3 51

24就是第67大的數字啦!

我們再用這種方法把另乙個樣例試一遍。和=

12+2+

0+0=

14 =12+

2+0+

0=14所以,

3214

3214

是字典序第15的數字。

我們設num

[i] num

[i]表示第

i i

個數字(從左往右數),a[

i]' role="presentation">a[i

]a[i

]為nu

m[1]

n um

[1]到nu

m[i−

1]n um

[i−1

]中,比nu

m[i]

n um

[i]大的數字個數,則an

s=((

∑i=1

n(nu

m[i]

−a[i

]−1)

×(n−

1)!)

)+1 ans

=((∑

i=1n

(num

[i]−

a[i]

−1)×

(n−1

)!))

+1本題要用高精度!

#include 

#include

#include

#include

using

namespace

std;

const

int maxn=100;

int n,x,num[101],a[101][maxn+1],size,k,b[101],t,c[maxn+1],o,kk,tot;

string s;

int main()

} while (++tot)

if (tot>1) printf(",");

size=s.size();

k=1;

for (int i=1;i//讀入,分離數字

if (s[i]=='(')

break;

} for (int i=1;i<=n;i++) //求出答案

}c[maxn]++; //加1

t=0;

for (int i=maxn;i>=1;i--)

kk=1;

while (!c[kk]) kk++;

for (int i=kk;i<=maxn;i++) printf("%d",c[i]);

}return

0;}

康托展開 全排列

今天找到了一篇非常好的介紹康托展開的文章!其核心是這一張圖 letter 儲存所需字母表 void initletter 初始化字母表 int fact int n 階乘 return result void output vector v 輸出生成的結果 cout endl void divisi...

康托展開 全排列

對於n個數的全排列,共有n!中排列方式,如何求某乙個序列在整個排列中的次序 從小到大 以9的全排枚舉例 842697513是1 9全排列的第幾個?高中數學排列組合問題,只需要做到不重不漏 首先看第一位為8,那麼第一位為1 7的全排列都比它小,共有7 8!個。在第一位為8的情況下,其次看第二位為4,那...

排列序數 康托展開)

如果用a b c d這4個字母組成乙個串,有4 24種,如果把它們排個序,每個串都對應乙個序號 abcd 0 abdc 1 acbd 2 acdb 3 adbc 4 adcb 5 bacd 6 badc 7 bcad 8 bcda 9 bdac 10 bdca 11 cabd 12 cadb 13 ...