1. 程式人生 > >排列的字典序問題Permrank題解

排列的字典序問題Permrank題解

先附上n=4的時候的4*3!=24種情況

1 23 4     1 2 4 3     1 3 2 4    1 3 4 2     1 4 2 3     1 4 3 2

2 13 4     2 1 4 3     2 3 1 4    2 3 4 1     2 4 1 3     2 4 3 1

3 12 4     3 1 4 2     3 2 1 4    3 2 4 1     3 4 1 2     3 4 2 1

4 12 3     4 1 3 2     4 2 1 3    4 2 3 1     4 3 1 2     4 3 2 1

這裡現注意第一點,1 2 3 4序號為0,4 3 2 1的序號為15

不需要全排列出來然後一個一個判斷,那樣可能會爆時間,這裡有個更好的規律方法

這裡舉個2 3 4 1的例子

1 23 4     1 2 4 3     1 3 2 4    1 3 4 2     1 4 2 3     1 4 3 2

2 13 4     2 1 4 3     2 3 1 4    2 3 4 1     2 4 1 3    2 4 3 1

3 12 4     3 1 4 2     3 2 1 4    3 2 4 1     3 4 1 2     3 4 2 1

4 12 3     4 1 3 2     4 2 1 3    4 2 3 1     4 3 1 2     4 3 2 1

“2  3  4  1”從前往後迴圈,現寫出2 3 4 1的序號:

2 3 4 1=(2-1)*3!+(2-1)*2! +(2-1)*1! +1 -1=6+2+1+1-1=9

從第一位2開始迴圈,判斷第a[i]位在i後面所有的數中大了多少個,像2在後面是大了一個自己是第二個(倒數第幾,這種意思只可意會不可言傳=  =),然後(2-1)。其實這個a[i]大了後面1個就是(2-1)=1這個1,這兩個意思是一樣的。思路是一樣的

例如這個2,(2-1)*3!就是6,就除去了所有1開頭的6個數!!保留了其他的。

這樣實質就是每次減去一種情況,再減去一種情況......就留下來了我們所需要的第幾位數

但是可以優化:

for (int f=1;f<=x-1;f++)

              if (a[z]>a[f]) y - -;

從前往後面找,比如2 3 4 1 中的3,從第一位找到i-1位,只要比a[i]小,那麼就y - -,這樣子就求出來了ronaldo函式+1的值。

這裡用一個函式來求ronaldo(鄙人喜歡C羅CristianoRonaldo)

sum+=ronaldo(i,a[i],i)*j[i-1]

這裡j[i]是階乘,因為考試時候這道題範圍是n<=13;這就是專門

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
using namespace std;
long long  a[14],j[15]={1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600};
int n,sum=0;
int ronaldo(int x,int y,int z)
{
	if (x==1) return a[x]-1;
	if (x==n) return 1;
	for (int f=1;f<=x-1;f++)
		if (a[z]>a[f]) y--;
	return y-1;
}
int main()
{
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
		scanf("%d",&a[i]);	
	for (int i=1;i<=n;i++)
		sum=sum+ronaldo(i,a[i],i)*j[n-i];
	cout<<sum-1<<endl;//因為從0開始算第一個
	next_permutation(a+1,a+n+1);
	for (int i=0;i<=n-1;i++)
		cout<<a[i]<<" ";
}

給我打表用的- -

然後由上述式子迴圈一遍後輸出sum-1  因為第一個序號為0

最後用next_permutation(a,a+n)  這裡不知道怎麼從1開始,所以我的陣列從1開始只好向前推一位,然後用next_permutation(a,a+n);這個函式很強大的

                                                                                                  By   Carry