zoukankan      html  css  js  c++  java
  • 康托展开与逆康托展开模板(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
    ",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]," 
    "[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
  • 相关阅读:
    java笔记
    java面向对象
    Oracle数据库基础
    Java中的集合和常用类
    Java面向对象的三个特征
    Java中的类与对象
    Java中的冒泡排序
    JAVA中的一些内置方法
    JAVA中的数据类型
    SSH整合
  • 原文地址:https://www.cnblogs.com/asdfsag/p/10084533.html
Copyright © 2011-2022 走看看