第几是谁?

时间限制:3000 ms  |  内存限制:65535 KB
难度:3
 
描述
现在有"abcdefghijkl”12个字符,将其按字典序排列,如果给出任意一种排列,我们能说出这个排列在所有的排列中是第几小的。但是现在我们给出它是第几小,需要你求出它所代表的序列.
 
输入
第一行有一个整数n(0<n<=10000);
随后有n行,每行是一个整数m,它代表着序列的第几小;
输出
输出一个序列,占一行,代表着第m小的序列。
样例输入
3
1
302715242
260726926
样例输出
abcdefghijkl
hgebkflacdji
gfkedhjblcia


  

解题思路:

康托展开:可以已知序列求其字典序中的序数,也可已知字典序的序数求其序列

   PS : nyoj -139 是本题的逆向过程,可参看前边的博文

 1 #include <cstdio>
 2 #include <string>
 3 #include <iostream>
 4 
 5 using namespace std;
 6 
 7 int fac[13];   //  存储阶乘
 8 int num[13];   // num[i]存储从小到大第i个未用过的字母编号
 9 
10 void cal_fac()// 计算阶乘
11 {
12     fac[0] = 1;
13     for(int i = 1; i < 13; ++i)
14         fac[i] = fac[i-1] * i;
15 }
16 
17 void init()   // 初始化序列
18 {
19     for(int i = 0; i < 13; ++i)
20         num[i] = i;
21 }
22 
23 void solve(int cnt)
24 {
25     for(int i = 0; i < 12; ++i)
26     {
27         int t = cnt / fac[11 - i];
28         printf("%c", num[t] + 'a');
29         for(int j = t; j < 11; ++j) // 用过之后就覆盖掉,保证序列都是没用过的
30             num[j] = num[j+1];
31         cnt %= fac[11 - i];
32     }
33     printf("\n");
34 }
35 
36 int main()
37 {
38     int n, cnt;
39     cal_fac();
40     scanf("%d", &n);
41     while(n--)
42     {
43         scanf("%d", &cnt);
44         init();
45         solve(cnt-1);  // 注意这里要减一
46     }
47     return 0;
48 }

 

posted on 2013-03-08 17:34  可笑痴狂  阅读(1399)  评论(0)    收藏  举报