NYOJ--139--我排第几个(康托展开)
我排第几个
时间限制:1000 ms | 内存限制:65535 KB
难度:3
- 描述
-
现在有"abcdefghijkl”12个字符,将其所有的排列中按字典序排列,给出任意一种排列,说出这个排列在所有的排列中是第几小的?
- 输入
- 第一行有一个整数n(0<n<=10000);
随后有n行,每行是一个排列; - 输出
- 输出一个整数m,占一行,m表示排列是第几位;
- 样例输入
-
3 abcdefghijkl hgebkflacdji gfkedhjblcia
- 样例输出
-
1 302715242 260726926
1 /* 2 Name: NYOJ--139--我排第几个 3 Copyright: ©2017 日天大帝 4 Author: 日天大帝 5 Date: 29/04/17 10:49 6 Description: 康托展开 7 */ 8 #include<iostream> 9 using namespace std; 10 int main(){ 11 ios::sync_with_stdio(false); 12 int jiecheng[15]; 13 jiecheng[1] = 1; 14 for(int i=2; i<14; ++i){ 15 jiecheng[i] = i * jiecheng[i-1]; 16 } 17 int t;cin>>t; 18 while(t--){ 19 string str; 20 cin>>str; 21 int num = 0; 22 for(int i=0; i<str.size(); ++i){ 23 int cnt = 0 ; 24 for(int j=i+1; j<str.size(); ++j){ 25 if(str[i] > str[j]) 26 cnt++; 27 } 28 num += cnt*jiecheng[str.size()-i-1]; 29 } 30 cout<<num+1<<endl; 31 } 32 return 0; 33 }
看了这个例子应该好理解点:
例1 {1,2,3,4,5}的全排列,并且已经从小到大排序完毕
(1)找出第96个数
首先用96-1得到95
用95去除4! 得到3余23
有3个数比它小的数是4
所以第一位是4
用23去除3! 得到3余5
有3个数比它小的数是4但4已经在之前出现过了所以第二位是5(4在之前出现过,所以实际比5小的数是3个)
用5去除2!得到2余1
有2个数比它小的数是3,第三位是3
用1去除1!得到1余0
有1个数比它小的数是2,第二位是2
最后一个数只能是1
所以这个数是45321
(2)找出第16个数
首先用16-1得到15
用15去除4!得到0余15
用15去除3!得到2余3
用3去除2!得到1余1
用1去除1!得到1余0
有0个数比它小的数是1
有2个数比它小的数是3 但由于1已经在之前出现过了所以是4(因为1在之前出现过了所以实际比4小的数是2)
有1个数比它小的数是2 但由于1已经在之前出现过了所以是3(因为1在之前出现过了所以实际比3小的数是1)
有1个数比它小得数是2 但由于1,3,4已经在之前出现过了所以是5(因为1,3,4在之前出现过了所以实际比5小的数是1)
最后一个数只能是2
所以这个数是14352