zoukankan      html  css  js  c++  java
  • topcoder srm 661 div1

    problem1 link

    $N+1$到$M$ 之间的数字要包含所有1到$N$之间出现的质因子的最高幂即可。

    problem2 link

    从第一个节点到第$N$个节点依次考虑。对于第$i$个节点来说,其颜色为$j$时,可以选择与前面的连边或者不连边,方案数为$1+(i-1)+g(i-1,j)$。其中$g(x,y)$ 表示前$x$个节点中,颜色为$y$ 的节点的个数

    所以节点$i$的方案数为$f(i)=sum_{j=1}^{K}(1+i-1-g(i-1,j))=K*i-sum_{j=1}^{K}g(i-1,j)=K*i-(i-1)=$

    $K+(K-1)(i-1)$

    所以最后的答案为:

    $ans=prod_{i=1}^{N}f(i)$
    $=prod_{i=1}^{N}(K+(K-1)(i-1))$
    $=prod_{i=0}^{N-1}(K+(K-1)i)$
    $=prod_{j=0}^{min(M-1,N-1)}(K+(K-1)j)^{frac{N-1-j}{M}+1}$

    最后一步是由于$[1,N]$之间的数字模$M$会出现循环。

    problem3 link

    相连的顶点会把整个区间分成若干段。预处理四个数组:

    (1) $L[i][j]$表示[i,j]是一段,这一段距离左端点最远的点的距离
    (2) $R[i][j]$表示[i,j]是一段,这一段距离右端点最远的点的距离 

    (3) $S[i][j]$表示[i,j]是一段,这一段中距离最远的两点之间的距离

    (4)$D[i][j]$表示这一段左右两个端点的距离

    然后二分答案。设为$mid$.设 $dp[i][j]$表示已经把$j$对顶点连了起来,最后一对是在$i$的位置时以$i$作为路径的结尾的最小值。那么每次新连一对的时候,要保证前面不能出现大于$mid$的情况。

    code for problem1

    #include <algorithm>
    #include <vector>
    using namespace std;
    
    class MissingLCM {
     public:
      int getMin(int N) {
        if (N == 1) {
          return 2;
        }
        long long result = 0;
        std::vector<bool> tags(N + 1, false);
        for (int i = 2; i <= N; ++i) {
          if (!tags[i]) {
            for (int j = i + i; j <= N; j += i) {
              tags[j] = true;
            }
            long long t = 1;
            while (t <= N / i) {
              t *= i;
            }
            result = std::max(result, N % t == 0 ? N + t : N / t * t + t);
          }
        }
        return static_cast<int>(result);
      }
    };

    code for problem2

    class ColorfulLineGraphs {
     public:
      int countWays(long long N, long long K, int M) {
        long long result = 1;
        for (int i = 0; i < M && i < N; ++i) {
          long long x = K + (K - 1) * i;
          long long y = (N - 1 - i) / M + 1;
          result = result * Pow(x, y, M) % M;
        }
        return static_cast<int>(result);
      }
    
     private:
      long long Pow(long long x, long long y, int M) {
        x %= M;
        long long result = 1;
        while (y != 0) {
          if (y % 2 == 1) {
            result = result * x % M;
          }
          x = x * x % M;
          y /= 2;
        }
        return result;
      }
    };

    code for problem3

    #include <algorithm>
    #include <cstring>
    #include <vector>
    
    constexpr int kMaxN = 200;
    int L[kMaxN][kMaxN];
    int R[kMaxN][kMaxN];
    int S[kMaxN][kMaxN];
    int D[kMaxN][kMaxN];
    int dp[kMaxN][kMaxN + 1];
    
    class BridgeBuilding {
     public:
      int minDiameter(const std::vector<int> &a, const std::vector<int> &b, int K) {
        int n = static_cast<int>(a.size()) + 1;
        std::vector<int> prefix_a(n);
        std::vector<int> prefix_b(n);
        for (int i = 1; i < n; ++i) {
          prefix_a[i] = prefix_a[i - 1] + a[i - 1];
          prefix_b[i] = prefix_b[i - 1] + b[i - 1];
        }
        auto Dist = [&](int a, int b, int t) {
          if (a >= b) {
            return 0;
          }
          return t == 0 ? prefix_a[b] - prefix_a[a] : prefix_b[b] - prefix_b[a];
        };
        auto GetMax = [&](int left, int right) {
          int number = right - left;
          auto Get = [&](int k) {
            if (k <= number) {
              return Dist(left, left + k, 0);
            }
            return Dist(left, right, 0) + Dist(right - (k - number), right, 1);
          };
          int total = Dist(left, right, 0) + Dist(left, right, 1);
          int tmax = 0;
          for (int L = 0, R = 0; L < number * 2; ++L) {
            if (R <= L) {
              R = L + 1;
            }
            int t = Get(L);
            while (R < number * 2 && Get(R) - t < total / 2) {
              int p = Get(R) - t;
              tmax = std::max(tmax, std::min(p, total - p));
              ++R;
            }
            int p = Get(R) - t;
            tmax = std::max(tmax, std::min(p, total - p));
          }
          return tmax;
        };
        for (int i = 0; i < n; ++i) {
          for (int j = i + 1; j < n; ++j) {
            int s0 = Dist(i, j, 0);
            int s1 = Dist(i, j, 1);
            D[i][j] = std::min(s0, s1);
            S[i][j] = GetMax(i, j);
            L[i][j] = R[i][j] = 0;
            for (int k = i; k <= j; ++k) {
              L[i][j] =
                  std::max(L[i][j], std::min(Dist(i, k, 0), Dist(k, j, 0) + s1));
              L[i][j] =
                  std::max(L[i][j], std::min(Dist(i, k, 1), Dist(k, j, 1) + s0));
              R[i][j] =
                  std::max(R[i][j], std::min(Dist(k, j, 0), Dist(i, k, 0) + s1));
              R[i][j] =
                  std::max(R[i][j], std::min(Dist(k, j, 1), Dist(i, k, 1) + s0));
            }
          }
        }
    
        auto Check = [&](int mid) {
          memset(dp, -1, sizeof(dp));
          for (int i = 0; i < n; ++i) {
            if (prefix_a[i] + prefix_b[i] <= mid) {
              dp[i][1] = std::max(prefix_a[i], prefix_b[i]);
            }
          }
          for (int i = 0; i < n; ++i) {
            for (int j = 1; j < K; ++j) {
              if (dp[i][j] != -1) {
                for (int k = i + 1; k < n; ++k) {
                  if (S[i][k] <= mid && dp[i][j] + L[i][k] <= mid) {
                    int v = std::max(R[i][k], dp[i][j] + D[i][k]);
                    if (dp[k][j + 1] == -1 || dp[k][j + 1] > v) {
                      dp[k][j + 1] = v;
                    }
                  }
                }
              }
            }
          }
          int result = std::numeric_limits<int>::max();
          for (int i = K - 1; i < n; ++i) {
            if (dp[i][K] != -1 && Dist(i, n - 1, 0) + Dist(i, n - 1, 1) <= mid) {
              result = std::min(result, dp[i][K] + std::max(Dist(i, n - 1, 0),
                                                            Dist(i, n - 1, 1)));
            }
          }
          return result <= mid;
        };
        int result = std::numeric_limits<int>::max();
        int left = 0, right = result;
        while (left <= right) {
          int mid = (left + right) >> 1;
          if (Check(mid)) {
            result = std::min(result, mid);
            right = mid - 1;
          } else {
            left = mid + 1;
          }
        }
        return result;
      }
    };
  • 相关阅读:
    php No input file specified 错误提示
    yii 隐藏index.php
    phpstudy 配置 sqlserver
    xdebug3 配置信息
    composer 更新
    mysql 命令行 导入大型文件
    使用 DBExportDoc V1.0 For MySQL 导出数据库表结构说明文档
    聚合数据接口调用实例
    servlet
    JDBC
  • 原文地址:https://www.cnblogs.com/jianglangcaijin/p/6867299.html
Copyright © 2011-2022 走看看