康拓展开

Posted yijiull

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了康拓展开相关的知识,希望对你有一定的参考价值。

 

技术分享
 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 }
View Code

 

以上是关于康拓展开的主要内容,如果未能解决你的问题,请参考以下文章

hdoj1043 Eight(逆向BFS+打表+康拓展开)

康拓展开

nyoj139--我排第几个 (康拓展开)

康拓展开模板

全排序与康拓展开

康拓展开-----两个排列的位置之差