NYOJ--139--我排第几个(康托展开)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

以上是关于NYOJ--139--我排第几个(康托展开)的主要内容,如果未能解决你的问题,请参考以下文章

康托展开-全排列应用

[学习][Math]康托展开和逆康托展开

康托展开及其逆运算

康托展开

康托展开和逆康托展开

康托展开与康托展开的逆运算