第几是谁?
时间限制: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 }