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

    #include <bits/stdc++.h>
    using namespace std ;
    //返回数组a中当下顺序的康拖映射
    typedef unsigned long long ll ;
    ll b[30] ;
    //对前 10 个自然数(0 ~ 9)的阶乘存入表
    //以免去对其额外的计算
    ll fact[22] ;
    /**
     * @brief 康拓展开
     *
     * @param[in] permutation 输入的一个全排列
     * @param[out] num 输入的康拓映射,即是第几个全排列
     */
    ll contor(vector<ll> permutation) {
        ll num = 0;
        ll len = permutation.size();
        for (ll i = 0; i < len; ++i) {
            ll cnt = 0; // 在 i 之后,比 i 还小的有几个
            for (ll j = i + 1; j < len; ++j)
                if (permutation[i] > permutation[j]) ++cnt;
            num += cnt * fact[len - i - 1];
        }
        return num + 1;
    }
    //对前 10 个自然数(0 ~ 9)的阶乘存入表
    //以免去对其额外的计算
    /**
     * @brief 逆康拓展开
     *
     * @param[in] bits 给定全排列的使用数字个数
     * @param[in] num 给定全排列的次位
     * @param[out] permutation 输出对应的全排列
     */
    vector<ll> revContor(ll bits, ll num) {
        num = num - 1; //有 num - 1 个排列比目标序列要小
        vector<bool> vis(bits + 1, false);
        vector<ll> permutation(bits, -1);
    
        ll n, residue = num;
        for (ll i = 0; i < bits; ++i) {
            n = residue / (fact[bits - i - 1]);
            residue = residue % (fact[bits - i - 1]);
    
            for (ll j = 1; j <= bits; ++j) {
                if (!vis[j] && !(n--)) {
                    vis[j] = true;
                    permutation[i] = j;
                    break;
                }
            }
        }
        return permutation;
    }
    
    
    int main()
    {
      int n , m ;
      cin >> n >> m ;
      fact[0] = 1;
      for(ll i = 1; i <= n ;i ++)
       fact[i] = fact[i - 1] * i ;
      for(int i = 1; i <= m ;i ++)
       {
         char s[2] ;
         cin >> s ;
         if(s[0] == 'P')
          {
            ll x ;cin >> x ;
            vector<ll> t = revContor(n , x) ;
            for(auto xx : t)
             cout << xx << " " ;
            puts("") ;
          }
          else
           {
             vector<ll> b ;
             for(ll i = 1 , x ; i <= n ;i ++) cin >> x , b.push_back(x) ;
             cout << contor(b) << endl ;
           }
       }
      return 0 ;
    }
    
    
    每次做题提醒自己:题目到底有没有读懂,有没有分析彻底、算法够不够贪心、暴力够不够优雅。
  • 相关阅读:
    Java基础--阻塞队列ArrayBlockingQueue
    Java基础--反射Reflection
    Java基础--对象克隆
    Java基础--HashCode
    Java基础--序列化Serializable
    OpenCV 绘制图像直方图
    PHP isset, array_key_exists配合使用, 并解决效率问题
    安装XDEBUG步骤及问题
    设计模式例子
    适配器模式例子
  • 原文地址:https://www.cnblogs.com/spnooyseed/p/12870859.html
Copyright © 2011-2022 走看看