• 康托展开与康托逆展开


    #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 ;
    }
    
    
    每次做题提醒自己:题目到底有没有读懂,有没有分析彻底、算法够不够贪心、暴力够不够优雅。
  • 相关阅读:
    C++开发系列-友元函数 友元类
    C++开发系列-C语言的malloc与C++的new分配空间
    C++开发系列-内联函数
    iOS开发系列-Foundation与CoreFoundation内存管理
    C开发系列-字符串
    C开发系列-数组
    列表 元组 字典
    神奇的print
    while 语句的逻辑
    <Web Crawler><Java><thread-safe queue>
  • 原文地址:https://www.cnblogs.com/spnooyseed/p/12870859.html
Copyright © 2020-2023  润新知