1 #include <bits/stdc++.h>
2 using namespace std;
3 //康托展开求法:
4 //比如2143 这个数,求其展开:
5 //从头判断,至尾结束,
6 //① 比 2(第一位数)小的数有多少个->1个就是1,1*3!
7 //② 比 1(第二位数)小的数有多少个->0个0*2!
8 //③ 比 4(第三位数)小的数有多少个->3个就是1,2,3,但是1,2之前已经出现,所以是 1*1!
9 //将所有乘积相加=7
10 //比该数小的数有7个,所以该数排第8的位置。
11 int fac[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320}; //i的阶乘为fac[i]
12 // 康托展开-> 表示数字a是 a的全排列中从小到大排,排第几
13 // n表示1~n个数 a数组表示数字。
14 int kangtuo(int n, char a[]){
15 int sum = 0;
16 for(int i = 0; i < n; i++){
17 int t = 0;
18 for(int j = i + 1; j < n; j++)
19 if(a[i] > a[j]) t++;
20 sum += t * fac[n - i - 1];
21 }
22 return sum+1;
23 }
24 //逆运算的方法:
25 //假设求4位数中第17个位置的数字。
26 //① 17减去1 → 16
27 //② 16 对3!作除法 → 得2余4
28 //③ 4对2!作除法 → 得2余0
29 //④ 0对1!作除法 → 得0余0
30 //据上面的可知:
31 //我们第一位数(最左面的数),比第一位数小的数有2个,显然 第一位数为→ 3
32 //比第二位数小的数字有2个,所以 第二位数为→4
33 //比第三位数小的数字有0个,所以第三位数为→1
34 //第四位数剩下 2
35 //该数字为 3412 (正解)
36 //int fac[] = {1,1,2,6,24,120,720,5040,40320};
37 //康托展开的逆运算,{1...n}的全排列,中的第k个数为s[]
38 void reverse_kangtuo(int n, int k, char s[]){
39 int vis[8]={0};
40 s[k] = 0;
41 --k;
42 for(int i = 0; i < n; i++){
43 int t = k / fac[n - i - 1];
44 int j;
45 for (j = 1; j <= n; j++){
46 if (!vis[j]){
47 if (t == 0) break;
48 --t;
49 }
50 }
51 s[i] = '0' + j;
52 vis[j] = 1;
53 k %= fac[n - i - 1];
54 }
55 }
56 int main(){
57 int n;
58 char s[11];
59 while(cin>>n) {
60 reverse_kangtuo(4, n , s);
61 cout<<s<<endl;
62 }
63 }