我排第幾個——康託展開
阿新 • • 發佈:2018-12-24
描述
現在有"abcdefghijkl”12個字元,將其所有的排列中按字典序排列,給出任意一種排列,說出這個排列在所有的排列中是第幾小的?
- 輸入
- 第一行有一個整數n(0<n<=10000);
隨後有n行,每行是一個排列; - 輸出
- 輸出一個整數m,佔一行,m表示排列是第幾位;
- 樣例輸入
-
3 abcdefghijkl hgebkflacdji gfkedhjblcia
- 樣例輸出
-
1 302715242
260726926
-
給大家說下什麼叫康託展開
-
如 {1,2,3} 按從小到大排列一共6個:123 132 213 231 312 321。想知道321是{1,2,3}中第幾個大的數。
這樣考慮:第一位是3,小於3的數有1、2 。所以有2*2!個。再看小於第二位,小於2的數只有一個就是1 ,所以有1*1!=1 所以小於32
的{1,2,3}排列數有2*2!+1*1!=5個。所以321是第6個大的數。2*2!+1*1!是康託展開。
再舉個例子:1324是{1,2,3,4}排列數中第幾個大的數:第一位是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<iostream> #include<stdio.h> using namespace std; int f(int n); long long KT(int n,int b[],long long f[]); int main(void){ long long f[13]; f[0]=1; for(long long i=1;i<13;i++) f[i]=f[i-1]*i; int s; cin>>s; while(s--){ char a[12]; int a1[12]; scanf("%s",a); for(int i=0;i<12;i++) a1[i]=(int)(a[i]-96); cout<<KT(12,a1,f)<<endl; } } int f(int n){ long long s=1; for(int i=1;i<=n;i++) s=s*i; return s; } long long KT(int n,int b[],long long f[]){ int i,j,t; long long sum=0; for(i=0;i<n;i++){ t=0; for(j=i+1;j<n;j++) if(b[j]<b[i]) t++; sum+=t*f[n-i-1]; } return sum+1; }