逆康托展開 全排列

2021-07-11 17:48:55 字數 1177 閱讀 4589

康托展開原公式:

把乙個整數x展開成如下形式:

x=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[2]*1!+a[1]*0!

其中a[i]為當前未出現的元素中是排在第幾個(從0開始),並且0<=a[i]

知道康托展開展開以後,我們可以很容易的得到一種新的求1-n全排列的方法,只需要求出1-n全排列中的第乙個,第二個...第n!個排列,即求出上式中的每一項係數a[n]。

依舊,舉個例子。

求1,2,3,4的全排列中,第21大的序列,

從0開始計數,

即為第20大的序列,將20分解:

20 = a4*3! + a3*2! + a2*1! + a1*0! 

等式左右兩邊同時除以3!,容易知道,

a4的可能取值有4種,不過是從0開始,實際值為3

,a3的取值是在a4確定的基礎之上,所以只有3中,從0開始,那麼實際值為2,同理可以知道,a3*2! + a2*1! + a1*0! 中每一項小於3!。利用輾轉相除法,將左式除以n!,將餘數除以(n-1)!,見下圖:

知道了a4、a3、a2、a1的值,就可以知道第一位數是子陣列[1,2,3,4]中第3大的元素 "4"(從0開始),第二位數是子陣列 [1,2,3] 中第1大的元素"2",第三位數是子陣列 [1,3] 中第0大的元素"1",第四位數是陣列 [3] 中第0大的元素"3",所以第21大的排列是4213。

#include #include using namespace std;

long int factory=;//階乘表

void uncontor(char res, int x, int n) //第x大數字序列(從0開始),1-n排列

visited[j] = true; //標記第consult大的已經被使用

res[n-1-i] = j+'0';

}}int main()

康托展開 全排列

今天找到了一篇非常好的介紹康托展開的文章!其核心是這一張圖 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,那...

全排列康托展開

n個元素有n 個不同的排列。將這n 個排列按字典序排列,並編號為0,1,n 1。每個排列的編號為其字典序值。例如,當n 3時,6 個不同排列的字典序值如下 0 1 2 3 4 5 123 132 213 231 312 321 任務 給定n 以及n 個元素的乙個排列,計算出這個排列的字典序值,以及按...