• 康托展开和逆康托展开


    {1,2,3,4,...,n}表示1,2,3,...,n的排列如 {1,2,3} 按从小到大排列一共6个。123 132 213 231 312 321 。

    代表的数字 1 2 3 4 5 6 也就是把10进制数与一个排列对应起来。

    他们间的对应关系可由康托展开来找到。

    如我想知道321是{1,2,3}中第几个大的数可以这样考虑 :

    第一位是3,当第一位的数小于3时,那排列数小于321 如 123、 213 ,小于3的数有1、2 。所以有2*2!个。再看小于第二位2的:小于2的数只有一个就是1 ,所以有1*1!=1 所以小于321的{1,2,3}排列数有2*2!+1*1!=5个。所以321是第6个大的数。 2*2!+1*1!+0*0!就是康托展开。

    再举个例子:1324是{1,2,3,4}排列数中第几个大的数:第一位是1小于1的数没有,是0个 0*3! 第二位是3小于3的数有1和2,但1已经在第一位了,所以只有一个数2 1*2! 。第三位是2小于2的数是1,但1在第一位,所以有0个数 0*1! ,所以比1324小的排列有0*3!+1*2!+0*1!=2个,1324是第三个大数。

     

     1 #include<string.h>
     2  #include<string>
     3  #include<ctime>
     4  #include<queue>
     5  #include<list>
     6  #include<map>
     7  #include<set>
     8  #define INF 999999999
     9  #define MAXN 10000000
    10  using namespace std;
    11  int fac[] = {1,1,2,6,24,120,720,5040,40320,362880};
    12  
    13  //康托展开:
    14  int cantor(int* a, int k) 
    15  {
    16      int i, j, tmp, num = 0;
    17      for (i = 0; i < k; i++) {
    18          tmp = 0;
    19          for (j = i + 1; j < k; j++)
    20              if (a[j] < a[i])
    21                  tmp++;
    22          num += fac[k - i - 1] * tmp;
    23      }
    24      return num;
    25  }
    26  
    27  //逆康托展开:
    28  int* uncantor(int x, int k) {
    29      int res[100];
    30      int i, j, l, t;
    31      bool h[100]={0};
    32      for (i = 1; i <= k; i++) 
    33      {
    34          t = x / fac[k - i];
    35          x -= t * fac[k - i];
    36          for (j = 1, l = 0; l <= t; j++)
    37              if (!h[j])
    38                  l++;
    39          j--;
    40          h[j] = true;
    41          res[i - 1] = j;
    42      }
    43      return res;
    44  }
    45  
    46  int main()
    47  {
    48      int n,a[1000];
    49      while(~scanf("%d",&n))
    50      {
    51          int i;
    52          for(i=0;i<n;i++)
    53              scanf("%d",&a[i]);
    54          int res=cantor(a,n);
    55          printf("%d
    ",res);
    56          int *b=uncantor(res,n);
    57          for(i=0;i<n;i++)
    58              printf("%d ",b[i]);
    59          putchar(10);
    60  
    61      }
    62      return 0;
    63  }
  • 相关阅读:
    对于git的认识
    第一篇博客
    结对编程
    对git的认识
    李叔同先生的《梦》
    51nod 1449 砝码称重
    LeetCode 21-29题解
    LeetCode 11-20题解
    LeetCode 6-10 题解
    LeetCode刷题重启博客
  • 原文地址:https://www.cnblogs.com/crazyapple/p/3213725.html
Copyright © 2020-2023  润新知