康托展开与逆康托展开模板(O(n^2)/O(nlogn))

O(n2)方法:

 1 namespace Cantor {
 2     const int N=100;
 3     int fac[N];
 4     void init() {
 5         fac[0]=1;
 6         for(int i=1; i<N; ++i)fac[i]=fac[i-1]*i;
 7     }
 8     int encode(int* a,int n) {
 9         int ret=0;
10         for(int i=n-1; i>=0; --i) {
11             int cnt=0;
12             for(int j=i+1; j<n; ++j)if(a[j]<a[i])++cnt;
13             ret+=cnt*fac[n-1-i];
14         }
15         return ret;
16     }
17     vector<int> decode(int x,int n) {
18         vector<int> ret;
19         vector<int> v;
20         for(int i=1; i<=n; ++i)v.push_back(i);
21         for(int i=n-1; i>=0; --i) {
22             ret.push_back(v[x/fac[i]]);
23             v.erase(v.begin()+x/fac[i]);
24             x%=fac[i];
25         }
26         return ret;
27     }
28 }

O(nlogn)方法(树状数组辅助):

 1 namespace Cantor {
 2     const int N=100;
 3     int fac[N],c[N],n,m;
 4     void init() {
 5         fac[0]=1;
 6         for(int i=1; i<N; ++i)fac[i]=fac[i-1]*i;
 7     }
 8     void setn(int _n) {
 9         n=_n;
10         m=1;
11         while(m<=n)m<<=1;
12         for(int i=0; i<m; ++i)c[i]=0;
13     }
14     int lowbit(int x) {
15         return x&-x;
16     }
17     void add(int u,int x) {
18         while(u<m) {
19             c[u]+=x;
20             u+=lowbit(u);
21         }
22     }
23     int rnk(int u) {
24         int ret=0;
25         while(u) {
26             ret+=c[u];
27             u-=lowbit(u);
28         }
29         return ret;
30     }
31     int kth(int k) {
32         int ret=0;
33         for(int i=m>>1; i; i>>=1) {
34             if(c[ret+i]<k) {
35                 ret+=i;
36                 k-=c[ret];
37             }
38         }
39         return ret+1;
40     }
41     int encode(int* a,int _n) {
42         setn(_n);
43         int ret=0;
44         for(int i=n-1; i>=0; --i) {
45             ret+=rnk(a[i])*fac[n-1-i];
46             add(a[i],1);
47         }
48         return ret;
49     }
50     vector<int> decode(int x,int _n) {
51         setn(_n);
52         vector<int> ret;
53         for(int i=1; i<=n; ++i)add(i,1);
54         for(int i=n-1; i>=0; --i) {
55             int t=kth(x/fac[i]+1);
56             ret.push_back(t);
57             add(t,-1);
58             x%=fac[i];
59         }
60         return ret;
61     }
62 }

测试代码:

 1 int main() {
 2     Cantor::init();
 3     int a[]= {1,2,3,4};
 4     do {
 5         printf("%d\n",Cantor::encode(a,4));
 6     } while(next_permutation(a,a+4));
 7     for(int i=0; i<24; ++i) {
 8         vector<int> v=Cantor::decode(i,4);
 9         for(int i=0; i<v.size(); ++i)printf("%d%c",v[i]," \n"[i==v.size()-1]);
10     }
11     return 0;
12 }

输出结果:

 1 0
 2 1
 3 2
 4 3
 5 4
 6 5
 7 6
 8 7
 9 8
10 9
11 10
12 11
13 12
14 13
15 14
16 15
17 16
18 17
19 18
20 19
21 20
22 21
23 22
24 23
25 1 2 3 4
26 1 2 4 3
27 1 3 2 4
28 1 3 4 2
29 1 4 2 3
30 1 4 3 2
31 2 1 3 4
32 2 1 4 3
33 2 3 1 4
34 2 3 4 1
35 2 4 1 3
36 2 4 3 1
37 3 1 2 4
38 3 1 4 2
39 3 2 1 4
40 3 2 4 1
41 3 4 1 2
42 3 4 2 1
43 4 1 2 3
44 4 1 3 2
45 4 2 1 3
46 4 2 3 1
47 4 3 1 2
48 4 3 2 1

 

posted @ 2018-12-07 18:55  jrltx  阅读(418)  评论(0编辑  收藏  举报