康托展开及其逆运算实现 C++

康托展开

康托展开

  • 求一个数在其全排列的次序

  • 规定a[n]为 在第n位后面且比其数值小的数字个数与 (n-1)! 的乘积,则此数次序为a[1..n]的总和+1;比如52341的次序为(4*4!+1*3!+1*2!+1*1!+0*0!)+1

  • 例码

    int fac(int t){
      if(t==0)    return 0;
      if(t==1)    return 1;
      return fac(t-1)*t;
    }
    int cantor(int num){
      int ans=0;
      vector  a;
      while(num!=0){
          a.push_back(num%10);
          num/=10;
      }
      for(int i=0;i=0;j--)
              if(a[i]>a[j])
                  cnt++;
          ans+=fac(i)*cnt;
      }
      return ans+1;
    }
    

逆运算

  • 通过在全排列中的次序求出这个数

  • 先自减一作为第一轮的被除数,从第1位到第n-1位依次循环,被除数除以(n-1)!,设其商数为m,余数为r,则这个数的第n位是数组a[1..n]还未被标记中第m+1小的数字,标记这个数字,r作为下一轮的被除数;第n位即最后数组a[1..n]还未被标记的数字

  • 例码

    int fac(int t){
      if(t==0)    return 0;
      if(t==1)    return 1;
      return fac(t-1)*t;
    }
    int get_from_cantor(int num, int len){
      num--;
      int m=1,ans=0;
      bool *book = new bool[len+1];
      for(int i=1;i=2;i--){
          int t=fac(i-1);
          m=num/t+1;
          while(book[m]==0){
              m++;
          }
          book[m]=0;
          ans*=10;
          ans+=m;
          num%=t;
      }
      m=1;
      while(book[m]==0){
          m++;
      }
      ans*=10;
      ans+=m;
      delete [] book;
      return ans;
    }
    

你可能感兴趣的:(康托展开及其逆运算实现 C++)