• topcoder srm 635 div1


    problem1 link

    首先枚举长度$L$。然后计算每一段长度$L$的差值最大公约数,然后差值除以最大公约数的结果可以作为当前段的关键字。然后不同段就可以比较他们的关键字,一样就是可以转化的。

    problem2 link

    对于那些一定要换的,把它们的places和cutoff拿出来,排个序。设它们为$p_{1},p_{2},..,p_{k},c_{1},c_{2},..,c_{k},$.最优的策略一定是从小到大挨个匹配。

    如果到了某个位置不能匹配,比如$t$.那么需要从那些不需要交换的组里面拿出一个$(np,nc)$,这个需要满足$npleq c_{t}$并且$nc$尽量大。

    problem3 link

     由于会有两个值不大于200,那么这两种最后会把整个序列最多分为401段。然后就是考虑把后面的两种也分成这么多段插进去就好。

    第一个问题,假设$f[n][m][k]$表示第一个颜色和第二个颜色各有$n$和$m$个,分成$k$段的方案数。有一个性质是每一段两个是交错的,所以数量差不会超过1,那么可以得到转移方程:

    (1)两个一样多组成一段:$n>0, m>0 ightarrow f[n][m][k]=2sum_{i=1}^{min(n,m)}f[n-i][m-i][k-1]$

    (2)第一个多一个组成一段:$n>0 ightarrow f[n][m][k]=sum_{i=1}^{min(n-1,m)}f[n-1-i][m-i][k-1]$

    (3)第二个多一个组成一段:$m>0 ightarrow f[n][m][k]=sum_{i=1}^{min(n,m-1)}f[n-i][m-1-i][k-1]$

    所以可以预处理对角线的前缀和可以在$O(nm(n+m))$的复杂度的计算完$f$

    第二个问题,假设现在有$m$段,将后面两个插进去,有多少方法。这$m$段有三种情况,第一种第三个颜色的数量多一个,第二种第四个颜色的数量多一个,第三种两种颜色一样多。设第三种颜色第四种颜色的数量分别为$a,b,aleq b$。这三种段的数量分别为$t,p,q$,那没有$t+p+q=m,p-t=b-a$。所以可以枚举$t$,然后$p,q$就可以都确定。令$X=a-t=b-p$,剩下的问题就是将$X$分成$m$个数字之和使得前$t+p$个数字可以为0,后面$q$个数字不能为0.这等价于将$Y=X+t+p-m$个数字分成$m$个数字之和,每个数字大于等于0.答案为$C_{Y+m-1}^{m-1}=C_{X+t+p-m-m-1}^{m-1}=C_{a-t+t+p-m+m-1}^{m-1}=C_{a+p-1}^{m-1}$

    所以$G(m,a,b)=sum_{t=0}^{min(a,m)}C_{m}^{t}*C_{m-t}^{p}*2^{q}*C_{a+p-1}^{m-1}[qgeq 0]$

    code for problem1

    #include <cmath>
    #include <vector>
    
    class SimilarRatingGraph {
     public:
      double maxLength(const std::vector<int> &date,
                       const std::vector<int> &rating) {
        int n = static_cast<int>(date.size());
        auto Length = [&](int idx) {
          double x = date[idx] - date[idx - 1];
          double y = rating[idx] - rating[idx - 1];
          return std::sqrt(x * x + y * y);
        };
        double result = 0;
        for (int L = n - 1; L > 1; --L) {
          int m = n - L + 1;
          std::vector<std::pair<long long, long long>> sum(m);
          for (int i = 0; i + L <= n; ++i) {
            int g = 0;
            for (int j = i + 1; j < i + L; ++j) {
              g = Gcd(g, date[j] - date[j - 1]);
              g = Gcd(g, std::abs(rating[j] - rating[j - 1]));
            }
            long long s0 = 0;
            long long s1 = 0;
            for (int j = i + 1; j < i + L; ++j) {
              int t0 = (date[j] - date[j - 1]) / g;
              int t1 = (rating[j] - rating[j - 1]) / g;
              s0 = s0 * 100007 + t0 + (j - i);
              s1 = s1 * 100007 + t1 + (j - i);
            }
            sum[i] = {s0, s1};
          }
          std::vector<double> sum_length(m, 0);
          for (int i = 1; i < L; ++i) {
            sum_length[0] += Length(i);
          }
          for (int i = 1; i < m; ++i) {
            sum_length[i] = sum_length[i - 1] + Length(i + L - 1) - Length(i);
          }
          for (int i = 0; i < m; ++i) {
            for (int j = i + 1; j < m; ++j) {
              if (sum[i] == sum[j]) {
                result = std::max(result, std::max(sum_length[i], sum_length[j]));
              }
            }
          }
        }
        return result;
      }
    
     private:
      int Gcd(int x, int y) { return y == 0 ? x : Gcd(y, x % y); }
    };

    code for problem2

    #include <algorithm>
    #include <vector>
    
    class StoryFromTCO {
     public:
      int minimumChanges(const std::vector<int> &places,
                         const std::vector<int> &cutoff) {
        std::vector<std::pair<std::pair<int, int>, bool>> good;
        std::vector<int> bad_places;
        std::vector<int> bad_cutoff;
        for (size_t i = 0; i < places.size(); ++i) {
          if (places[i] <= cutoff[i]) {
            good.push_back({{places[i], cutoff[i]}, false});
          } else {
            bad_places.push_back(places[i]);
            bad_cutoff.push_back(cutoff[i]);
          }
        }
        auto Sort = [&](size_t idx) {
          std::sort(bad_places.begin() + idx, bad_places.end());
          std::sort(bad_cutoff.begin() + idx, bad_cutoff.end());
        };
        auto FindBest = [&](int cut) -> int {
          int n = static_cast<int>(good.size());
          int bst = -1;
          for (int i = 0; i < n; ++i) {
            if (!good[i].second && good[i].first.first <= cut &&
                (bst == -1 || good[bst].first.second < good[i].first.second)) {
              bst = i;
            }
          }
          return bst;
        };
        Sort(0);
        size_t idx = 0;
        while (idx < bad_places.size()) {
          if (bad_places[idx] <= bad_cutoff[idx]) {
            ++idx;
            continue;
          }
          int bst = FindBest(bad_cutoff[idx]);
          if (bst == -1) {
            return -1;
          }
          bad_places.push_back(good[bst].first.first);
          bad_cutoff.push_back(good[bst].first.second);
          good[bst].second = true;
          Sort(idx);
        }
        return static_cast<int>(bad_cutoff.size());
      }
    };

    code for problem3

    #include <algorithm>
    #include <vector>
    
    constexpr int kMAXN = 100000;
    constexpr int kMAXM = 400;
    constexpr int kMod = 1000000009;
    
    long long fact[kMAXN + kMAXM + 1];
    long long fact_inv[kMAXN + kMAXM + 1];
    long long fpow[kMAXM + 2];
    
    int f[kMAXM / 2 + 1][kMAXM / 2 + 1][kMAXM + 1];
    
    class ColourHolic {
     public:
      int countSequences(std::vector<int> all) {
        std::sort(all.begin(), all.end());
        Initialize(all[2] + all[3] + all[0] + all[1]);
        if (all[2] == 0) {
          if (all[3] > 1) {
            return 0;
          } else {
            return 1;
          }
        }
        if (all[1] == 0) {
          if (all[2] == all[3]) {
            return 2;
          } else if (all[2] + 1 == all[3]) {
            return 1;
          } else {
            return 0;
          }
        }
    
        auto Get = [&](int m, int mul) {
          long long r = Compute(m + 1, all[2], all[3]);
          r += Compute(m, all[2], all[3]) * 2;
          r += Compute(m - 1, all[2], all[3]);
          return static_cast<int>(r % kMod * mul % kMod);
        };
    
        if (all[0] == 0) {
          return Get(all[1], 1);
        }
        int n = all[0];
        int m = all[1];
        f[0][1][1] = 1;
        for (int i = 1; i <= n; ++i) {
          f[i][i][1] = 2;
          f[i][i - 1][1] = 1;
          if (i + 1 <= m) {
            f[i][i + 1][1] = 1;
          }
        }
        int result = Get(1, f[n][m][1]);
        for (int k = 2; k <= n + m; ++k) {
          for (int i = 0; i <= n; ++i) {
            int t = 1;
            while (t <= m && i + t <= n) {
              Add(f[i + t][t][k - 1], f[i + t - 1][t - 1][k - 1]);
              ++t;
            }
          }
          for (int j = 1; j <= m; ++j) {
            int t = 1;
            while (t <= n && j + t <= m) {
              Add(f[t][j + t][k - 1], f[t - 1][j + t - 1][k - 1]);
              ++t;
            }
          }
          for (int i = 0; i <= n; ++i) {
            for (int j = 0; j <= m; ++j) {
              if (i > 0 && j > 0) {
                Add(f[i][j][k], f[i - 1][j - 1][k - 1] * 2);
              }
              if (i > 0) {
                Add(f[i][j][k], f[i - 1][j][k - 1]);
              }
              if (j > 0) {
                Add(f[i][j][k], f[i][j - 1][k - 1]);
              }
            }
          }
          Add(result, Get(k, f[n][m][k]));
        }
        return result;
      }
    
     private:
      void Add(int &x, int y) {
        if (y >= kMod) {
          y -= kMod;
        }
        x += y;
        if (x >= kMod) {
          x -= kMod;
        }
      }
    
      long long Compute(int m, int a, int b) {
        if (m == 0) {
          return 0;
        }
        long long result = 0;
        for (int t = 0; t <= a && t <= m; ++t) {
          int p = b - a + t;
          int q = m - p - t;
          if (q < 0) {
            continue;
          }
          result += C(m, t) * C(m - t, p) % kMod * fpow[q] % kMod *
                    C(a + p - 1, m - 1) % kMod;
        }
        return result % kMod;
      }
    
      void Initialize(int n) {
        fact[0] = fact_inv[0] = 1;
        fact[1] = fact_inv[1] = 1;
        for (int i = 2; i <= n; ++i) {
          fact[i] = fact[i - 1] * i % kMod;
          fact_inv[i] = GetInv(fact[i]);
        }
        fpow[0] = 1;
        for (int i = 1; i <= kMAXM + 1; ++i) {
          fpow[i] = fpow[i - 1] * 2 % kMod;
        }
      }
    
      long long C(int n, int m) {
        if (n < m || m < 0) {
          return 0;
        }
        return fact[n] * fact_inv[m] % kMod * fact_inv[n - m] % kMod;
      }
    
      long long GetInv(long long n) {
        int m = kMod - 2;
        long long r = 1;
        while (m != 0) {
          if ((m & 1) == 1) {
            r = r * n % kMod;
          }
          m >>= 1;
          n = n * n % kMod;
        }
        return r;
      }
    };
  • 相关阅读:
    截取小数位数(准确四舍五入及直接截取)
    水印
    用心整理的 献丑啦 一些关于http url qs fs ...模块的方法
    html禁止清除input文本输入缓存的两种方法
    flink写入elasticsearch报错!OOM内存溢出!连接异常关闭!
    实现网格建造系统
    AcWing 1064. 小国王
    AcWing 1052. 设计密码
    KMP 模板
    AcWing 1058. 股票买卖 V
  • 原文地址:https://www.cnblogs.com/jianglangcaijin/p/10002830.html
Copyright © 2020-2023  润新知