zoukankan      html  css  js  c++  java
  • 康托展开

    1. 康托展开

    X = A[0] * (n-1)! + A[1] * (n-2)! + … + A[n-1] * 0! 

    A[i] 指的是位于位置i后面的数小于A[i]值的个数,后面乘的就是后面还有多少个数的阶乘

    tips:这个算出来的数康拖展开值,是在所有排列次序 - 1的值,因此X+1即为在全排列中的次序,康托展开可逆(自然数 -> 序列)。

    ▲:康托展开的实质是计算当前排列在所有由小到大全排列中的名次。

    ▲:康托展开的原理就是从某个排序组合的首位开始,找出比当前这位数的个数,且之前没有出现过的数的个数乘以对应的阶乘,结果累加就是我们要求的值。//阶乘就理解为以前学过的排列组合,而不同数的阶乘也对数的次序进行了划分,如n=5时,1开头的数,就分布在1到4!。2开头的数,就分布在4!+1到2*4!

     1 int cantor(int *a,int n)
     2 {
     3     int ans=0;
     4     for(int i=0;i<n;i++)
     5     {
     6         int x=0,c=1,m=1;
     7         for(int j=i+1;j<n;j++)
     8         {
     9             if(a[j]<a[i]) x++;
    10             m*=c++;
    11         }
    12         ans+=m*x;
    13     }
    14     return ans;
    15 }

    2. 逆康托展开

    对数X逐个mod(n-i)!,商为几,则表示在第i位(i从第一位开始)后有几个数,然后用余数继续除阶乘求余。

    ▲:原理结合上面,可知在求余数的过程中,其实就是在给这些数定位

     1 void obcantor(int x,int n) //O(n^2)
     2 {
     3     vector<int>v; //存放当前可选数
     4     vector<int>a; //所求序列
     5     int ft[10],id=1;
     6     ft[0]=1;
     7     for(int i=1;i<=n;i++)
     8     {
     9         v.push_back(i);
    10         id*=i;
    11         ft[i]=id;
    12     }
    13     for(int i=n-1;i>=0;i--)
    14     {
    15         int s=x/ft[i];
    16         int t=x%ft[i];
    17         x=t;
    18         sort(v.begin(),v.end());
    19         a.push_back(v[s]); //剩余数里第t+1个
    20         v.erase(v.begin()+s);
    21     }
    22     //for(int i=0;i<n;i++)
    23     //    cout<<a[i]<<" ";
    24 }
  • 相关阅读:
    Java String字符串深入详解
    每日linux命令学习-sed
    每日linux命令学习-历史指令查询(history、fc、alias)
    每日linux命令学习-rpm命令
    每日linux命令学习-head命令和tail命令
    每日linux命令学习-lsattr和chattr
    每日linux命令学习-xargs命令
    每日linux命令学习-read命令
    测试mysql性能工具
    mysql 免安装版文件含义及作用
  • 原文地址:https://www.cnblogs.com/XXrll/p/11256393.html
Copyright © 2011-2022 走看看