• topcoder srm 545 div1


    problem1 link

    这个可以贪心地从前向后构造。假设当前已经的字符串为$S$,对于一个字符$c$来说,设将$c$加到$S$后得到的新串为$S^{'}$。那么如果$X+Y+Z ge minInv$,那么这个之后的构造就是有解的。其中$X$表示$S^{'}$中逆序对个数;$Y$表示剩下的字符与$S^{'}$中的字符构成的逆序对的个数;$Z$表示剩下的字符能构成的最大逆序对个数(从大到小排列即可)。

    problem2 link

    首先处理掉垂直发射的情况。剩下的就是不垂直的。直接枚举直线的斜率,即$(x, y)$且$x,y$ 互质。由于斜率为正以及为负是对称的,所以只考虑为正的情况。对于指定的斜率,一共可以画出$L+1$条线。这些线分为两部分,第一部分从矩形的上边出去;第二部分从矩形的右侧出去。对于第一部分,直线经过的格点的数目是确定的,所以只要统计有多少条即可。

    对于第二部分,起点越靠后,经过的格点数越少,它的规律是每$x$个经过的格点减少1.即假设从$(t,0)$出发的直线且从右侧出去时经过的格点是$p$,那么从$(t+x,0)$出发的直线经过的格点一定是$p-1$.假设$L=20,H=14,x=3,y=1$,那么从$(0,0),(1,0),(2,0)$出发的直线经过7个格点,从$(3,0),(4,0),(5,0)$出发的直线经过6个,依次类推,所以答案为$x*sum_{i=K}^{7}C_{i}^{K}=x*sum_{i=1}^{7}C_{i}^{K}=x*C_{8}^{K+1}$

    problem3 link

    每个数字最多有20位,所以只需要考虑20位即可。

    对于某一位来说,如果所有数字在这个位上全是1或者全是0,那么不需要考虑这一位。那么现在只需要考虑那么既有0又有1的位。一个分配的原则就是在某一位上所有为0的数字不能分配到一个颜色。

    考虑容斥原理。所有的情况有$2^n$种。减去在某一位上出现冲突而在其他位任意的情况(即这一位的所有的0都染成同一个颜色),这时候两个位同时冲突的情况就会多减了一次,所以再加上同时在两位上有冲突而其他位任意的情况。依次类推下去。

    code for problem1

    #include <string>
    #include <vector>
    using namespace std;
    
    class StrIIRec {
     public:
      string recovstr(int n, int minInv, string minStr) {
        if (n == 1) {
          return minStr;
        }
        while (static_cast<int>(minStr.size()) < n) {
          minStr += 'a';
        }
        std::string s = "";
        bool equal = true;
        int mask = (1 << n) - 1;
        int num = 0;
        for (int i = 0; i < n; ++i) {
          bool find_it = false;
          for (int j = 0; j < n; ++j) {
            char c = 'a' + j;
            if ((mask & (1 << j)) != 0 && (!equal || c >= minStr[i])) {
              int num0 = num;
              int remain_max_inv = GetMaxInv(mask ^ (1 << j), n);
              for (int k = 0; k < i; ++k) {
                if (s[k] > c) {
                  ++num0;
                }
              }
              if (num0 + remain_max_inv >= minInv) {
                s += c;
                num = num0;
                if (c > minStr[i]) {
                  equal = false;
                }
                find_it = true;
                mask ^= 1 << j;
                break;
              }
            }
          }
          if (!find_it) {
            return "";
          }
        }
        return s;
      }
    
      int GetMaxInv(int remain_mask, int n) {
        int result = 0;
        int pre = 0;
        for (int i = n - 1; i >= 0; --i) {
          if ((remain_mask & (1 << i)) != 0) {
            result += pre;
          } else {
            ++pre;
          }
        }
        result += (n - pre) * (n - pre - 1) / 2;
        return result;
      }
    };

    code for problem2

    #include <stdint.h>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <vector>
    
    class Spacetsk {
      static const int64_t mod = 1000000007;
    
     public:
      int countsets(int L, int H, int K) {
        Init(std::max(L, H) + 1);
        int64_t r = Binomial(H + 1, K) * (L + 1) % mod;
        if (K == 1) {
          return static_cast<int>(r);
        }
        for (int x = 1; x <= L; ++x) {
          for (int y = H; y >= 1; --y) {
            if (Gcd(x, y) != 1) {
              continue;
            }
            r += (Compute1(L, H, K, x, y) + Compute2(L, H, K, x, y)) << 1;
            r %= mod;
          }
        }
        return static_cast<int>(r);
      }
    
     private:
      int64_t Compute1(int L, int H, int K, int x, int y) {
        int x_right;
        if (H % y == 0) {
          x_right = L - H / y * x;
        } else {
          x_right = L - H * x / y - 1;
        }
        if (x_right < 0) {
          return 0;
        }
        int c = x_right + 1;
        int num = H / y + 1;
        return Binomial(num, K) * static_cast<int64_t>(c) % mod;
      }
    
      int64_t Compute2(int L, int H, int K, int x, int y) {
        int x_right;
        if (H % y == 0) {
          x_right = L - H / y * x;
        } else {
          x_right = L - H * x / y - 1;
        }
        ++x_right;
        if (x_right < 0) {
          x_right = 0;
        }
        int64_t r = 0;
        int64_t length = L - x_right;
        if ((length + 1) % x != 0) {
          int num = length / x + 1;
          int c = length % x + 1;
          r += Binomial(num, K) * static_cast<int64_t>(c) % mod;
          length -= c;
        }
        int max_num = length / x + 1;
        r += Binomial(max_num + 1, K + 1) * static_cast<int64_t>(x);
        r %= mod;
        return r;
      }
    
      int64_t Gcd(int64_t x, int64_t y) { return y == 0 ? x : Gcd(y, x % y); }
    
      int64_t Binomial(int a, int b) {
        if (a < b) {
          return 0;
        }
        if (a == 0 || a == b) {
          return 1;
        }
        return p[a] * q[b] % mod * q[a - b] % mod;
      }
    
      void Init(int n) {
        p.resize(n + 2);
        q.resize(n + 2);
        p[0] = q[0] = 1;
        for (int64_t i = 1; i < p.size(); ++i) {
          p[i] = p[i - 1] * static_cast<int64_t>(i) % mod;
          q[i] = Pow(p[i], mod - 2);
        }
      }
    
      int64_t Pow(int64_t a, int64_t b) {
        int64_t r = 1;
        while (b > 0) {
          if ((b & 1) == 1) {
            r = r * a % mod;
          }
          a = a * a % mod;
          b >>= 1;
        }
        return r;
      }
    
      std::vector<int64_t> p;
      std::vector<int64_t> q;
    };

    code for problem3

    #include <vector>
    #include <iostream>
    using namespace std;
    
    class SetAndSet {
     public:
      long long countandset(vector<int> A) {
        long long all = 0;
        for (size_t i = 0; i < A.size(); ++i) {
          all &= A[i];
        }
        for (size_t i = 0; i < A.size(); ++i) {
          A[i] ^= all;
        }
        std::vector<std::vector<int>> v(20, std::vector<int>());
        for (int i = 0; i < 20; ++i) {
          for (size_t j = 0; j < A.size(); ++j) {
            if ((A[j] & (1 << i)) == 0) {
              v[i].push_back(static_cast<int>(j));
            }
          }
        }
        std::vector<int> f(A.size());
        for (size_t i = 0; i < f.size(); ++i) {
          f[i] = i;
        }
        return dfs(0, f, 1ll, v, A);
      }
    
      long long dfs(size_t dep, const std::vector<int> &f, long long sgn,
                    const std::vector<std::vector<int>> &v,
                    const std::vector<int> &A) {
        if (dep == v.size()) {
          int tot = 0;
          for (size_t i = 0; i < f.size(); ++i) {
            if (f[i] == static_cast<int>(i)) {
              ++tot;
            }
          }
          return (1ll << tot) * sgn;
        }
        long long result = dfs(dep + 1, f, sgn, v, A);
        if (!v[dep].empty()) {
          static std::vector<int> h(50, 0);
          static int index = 0;
          std::vector<int> f_bak = f;
          ++index;
          for (size_t i = 0; i < v[dep].size(); ++i) {
            h[f[v[dep][i]]] = index;
          }
          int root = f_bak[v[dep][0]];
          for (size_t i = 0; i < A.size(); ++i) {
            if (h[f_bak[i]] == index) {
              f_bak[i] = root;
            }
          }
          result += dfs(dep + 1, f_bak, -sgn, v, A);
        }
        return result;
      }
    };
    

      

  • 相关阅读:
    数据挖掘-基本流程
    ArcGIS GP应用-GP模型服务发布
    ArcGIS GP应用-GP模型创建-缓冲区分析
    Hadoop2的Yarn和MapReduce2相关
    hadoop学习WordCount+Block+Split+Shuffle+Map+Reduce技术详解
    WordCount示例深度学习MapReduce过程
    数组的几种排序算法的实现
    hBase官方文档以及HBase基础操作封装类
    Hive SQL执行流程分析
    Hive SQL的编译过程
  • 原文地址:https://www.cnblogs.com/jianglangcaijin/p/8687400.html
Copyright © 2020-2023  润新知