• AtCoder Beginner Contest 270


    咕咕咕。

    D - Stones

    冲了发贪心,然后 WA 。

    然后想了个 DP,就令 \(dp_{n, 0/1}\) 表示石头总数为 \(n\) 时,先手/后手最多能拿多少个石头,然后跑个 \(O(nk)\) 的DP就完事了。

    AC代码
    // Problem: D - Stones
    // Contest: AtCoder - TOYOTA MOTOR CORPORATION Programming Contest 2022(AtCoder Beginner Contest
    // 270) URL: https://atcoder.jp/contests/abc270/tasks/abc270_d Memory Limit: 1024 MB Time Limit:
    // 2000 ms
    //
    // Powered by CP Editor (https://cpeditor.org)
    
    #include <bits/stdc++.h>
    
    #define CPPIO std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
    
    #ifdef BACKLIGHT
    #include "debug.h"
    #else
    #define logd(...) ;
    #define ASSERT(x) ;
    #define serialize() std::string("")
    #endif
    
    using i64 = int64_t;
    using u64 = uint64_t;
    
    void Initialize();
    void SolveCase(int Case);
    
    int main(int argc, char* argv[]) {
      CPPIO;
      int T = 1;
      // std::cin >> T;
      for (int t = 1; t <= T; ++t) {
        SolveCase(t);
      }
      return 0;
    }
    
    void Initialize() {}
    
    void SolveCase(int Case) {
      int n, k;
      std::cin >> n >> k;
    
      std::vector<int> a(k);
      for (int i = 0; i < k; ++i)
        std::cin >> a[i];
    
      std::vector<std::vector<int>> dp(n + 1, std::vector<int>(2, 0));
      dp[0][0] = 0;
      dp[0][1] = 0;
      for (int i = 1; i <= n; ++i) {
        for (int j = k - 1; j >= 0; --j) {
          if (i >= a[j]) {
            dp[i][0] = std::max(dp[i][0], dp[i - a[j]][1] + a[j]);
            dp[i][1] = i - dp[i][0];
          }
        }
      }
      logd(dp);
    
      std::cout << dp[n][0] << "\n";
    }
    
    

    E - Apple Baskets on Circle

    记走一圈为一轮,可以把结果相同的轮的贡献合并到一起算,从而加速模拟。

    假设 \(a\) 按大小排序后的数组为 \(b\),那么原过程等价于在 \(b\) 上从左往右走的过程,假设走到了 \(b_i\) ,则现在的一轮一轮等价于 \([i, n]\) 区间减 \(1\) 。假设 \(b_i\) 之前已经走了了 \(d\) 轮,那么接下来 \(\min(\lfloor \frac{k}{n - i} \rfloor, b_i - d)\) 轮的结果相同,这几轮的贡献可以 \(O(1)\) 计算。

    现在 \(k\) 可能还有剩余但不足以走完一轮,模拟一下即可。

    时间复杂度 \(O(n \log n)\),瓶颈在于排序,模拟的部分复杂度为 \(O(n)\)

    AC代码
    // Problem: E - Apple Baskets on Circle
    // Contest: AtCoder - TOYOTA MOTOR CORPORATION Programming Contest 2022(AtCoder Beginner Contest
    // 270) URL: https://atcoder.jp/contests/abc270/tasks/abc270_e Memory Limit: 1024 MB Time Limit:
    // 2000 ms
    //
    // Powered by CP Editor (https://cpeditor.org)
    
    #include <bits/stdc++.h>
    
    #define CPPIO std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
    
    #ifdef BACKLIGHT
    #include "debug.h"
    #else
    #define logd(...) ;
    #define ASSERT(x) ;
    #define serialize() std::string("")
    #endif
    
    using i64 = int64_t;
    using u64 = uint64_t;
    
    void Initialize();
    void SolveCase(int Case);
    
    int main(int argc, char* argv[]) {
      CPPIO;
      int T = 1;
      // std::cin >> T;
      for (int t = 1; t <= T; ++t) {
        SolveCase(t);
      }
      return 0;
    }
    
    void Initialize() {}
    
    void SolveCase(int Case) {
      int n;
      i64 k;
      std::cin >> n >> k;
    
      std::vector<i64> a(n);
      for (int i = 0; i < n; ++i)
        std::cin >> a[i];
    
      auto b = a;
      std::sort(b.begin(), b.end());
    
      i64 d = 0;
      for (int i = 0; i < n; ++i) {
        i64 r = n - i;
        if (k < n - i)
          break;
    
        i64 x = std::min(k / (n - i), b[i] - d);
        logd(i, x);
        d += x;
        k -= x * r;
      }
    
      for (int i = 0; i < n; ++i)
        a[i] = std::max(i64(0), a[i] - d);
      logd(a);
    
      for (int i = 0; i < n; ++i) {
        if (a[i] > 0 && k > 0) {
          --a[i];
          --k;
        }
      }
      ASSERT(k == 0);
    
      for (int i = 0; i < n; ++i)
        std::cout << a[i] << " \n"[i + 1 == n];
    }
    
    

    F - Transportation

    把机场和港口也看成节点的话,问题就转化成了的最小生成树问题。

    然后可能会有不使用机场和港口的情况,机场和港口都可用可不用,一共 \(4\) 种情况,那就跑 \(4\) 次 Kruskal 最小生成树算法。

    AC代码
    // Problem: F - Transportation
    // Contest: AtCoder - TOYOTA MOTOR CORPORATION Programming Contest 2022(AtCoder Beginner Contest
    // 270) URL: https://atcoder.jp/contests/abc270/tasks/abc270_f Memory Limit: 1024 MB Time Limit:
    // 4000 ms
    //
    // Powered by CP Editor (https://cpeditor.org)
    
    #include <bits/stdc++.h>
    
    #define CPPIO std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
    
    #ifdef BACKLIGHT
    #include "debug.h"
    #else
    #define logd(...) ;
    #define ASSERT(x) ;
    #define serialize() std::string("")
    #endif
    
    using i64 = int64_t;
    using u64 = uint64_t;
    
    void Initialize();
    void SolveCase(int Case);
    
    int main(int argc, char* argv[]) {
      CPPIO;
      int T = 1;
      // std::cin >> T;
      for (int t = 1; t <= T; ++t) {
        SolveCase(t);
      }
      return 0;
    }
    
    void Initialize() {}
    
    void SolveCase(int Case) {
      auto kruskal = [](int n, std::vector<std::array<int, 4>> E) {
        std::sort(E.begin(), E.end());
    
        std::vector<int> f(n + 2);
        std::iota(f.begin(), f.end(), 0);
    
        std::function<int(int)> find = [&](int x) { return x == f[x] ? x : f[x] = find(f[x]); };
    
        i64 ans = 0;
        for (auto [w, _, u, v] : E) {
          int fu = find(u), fv = find(v);
          if (fu == fv)
            continue;
    
          f[fu] = fv;
    
          ans += w;
        }
    
        for (int i = 0; i < n; ++i)
          if (find(i) != find(0))
            return std::numeric_limits<i64>::max();
    
        return ans;
      };
    
      int n, m;
      std::cin >> n >> m;
    
      std::vector<std::array<int, 4>> E;
    
      int airport = n, harbor = n + 1;
      std::vector<int> x(n);
      for (int i = 0; i < n; ++i) {
        std::cin >> x[i];
      }
      std::vector<int> y(n);
      for (int i = 0; i < n; ++i) {
        std::cin >> y[i];
      }
      std::vector<int> a(m), b(m), z(m);
      for (int i = 0; i < m; ++i) {
        int u, v, w;
        std::cin >> u >> v >> w;
        --u, --v;
        a[i] = u, b[i] = v, z[i] = w;
      }
    
      i64 ans = std::numeric_limits<i64>::max();
      {
        std::vector<std::array<int, 4>> E;
        for (int i = 0; i < n; ++i) {
          E.push_back({x[i], 1, i, airport});
        }
        for (int i = 0; i < n; ++i) {
          E.push_back({y[i], 1, i, harbor});
        }
        for (int i = 0; i < m; ++i) {
          E.push_back({z[i], 0, a[i], b[i]});
        }
        ans = std::min(ans, kruskal(n, E));
      }
      {
        std::vector<std::array<int, 4>> E;
        for (int i = 0; i < n; ++i) {
          E.push_back({y[i], 1, i, harbor});
        }
        for (int i = 0; i < m; ++i) {
          E.push_back({z[i], 0, a[i], b[i]});
        }
        ans = std::min(ans, kruskal(n, E));
      }
      {
        std::vector<std::array<int, 4>> E;
        for (int i = 0; i < n; ++i) {
          E.push_back({x[i], 1, i, airport});
        }
        for (int i = 0; i < m; ++i) {
          E.push_back({z[i], 0, a[i], b[i]});
        }
        ans = std::min(ans, kruskal(n, E));
      }
      {
        std::vector<std::array<int, 4>> E;
        for (int i = 0; i < m; ++i) {
          E.push_back({z[i], 0, a[i], b[i]});
        }
        ans = std::min(ans, kruskal(n, E));
      }
    
      std::cout << ans << "\n";
    }
    
    

    G - Sequence in mod P

    \(f(x) = Ax + B\),则可以算出 \(f^{-1}(x) = Cx + D\)

    \(X_n = G\) 等价于 \(f^x(S) = G\) ,这个式子和离散对数的式子很相似,考虑类似求解离散对数问题的大步小步算法(BSGS, baby-step giant-step)。

    \(M = \sqrt{p}\),则对于所有 \(x\) 都存在 \(0 \le A, B \le \sqrt{p}\) 使得 \(x = AM + B\) 成立,然后就有 \(f^x(S) = G\) 等价于 \(f^{AM}(S) = f^{-B}(G)\)

    由于 \(0 \le A, B \le \sqrt{p}\),所以可以先枚举等式的一边,记录结果取值以及对应步数;然后再枚举等式的另一边,看是否有结果取值相等的记录,若有则两边的步数相加就是一个可行的 \(x\)

    AC代码
    // Problem: G - Sequence in mod P
    // Contest: AtCoder - TOYOTA MOTOR CORPORATION Programming Contest 2022(AtCoder Beginner Contest
    // 270) URL: https://atcoder.jp/contests/abc270/tasks/abc270_g Memory Limit: 1024 MB Time Limit:
    // 4000 ms
    //
    // Powered by CP Editor (https://cpeditor.org)
    
    #include <bits/stdc++.h>
    
    #define CPPIO std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
    
    #ifdef BACKLIGHT
    #include "debug.h"
    #else
    #define logd(...) ;
    #define ASSERT(x) ;
    #define serialize() std::string("")
    #endif
    
    using i64 = int64_t;
    using u64 = uint64_t;
    
    void Initialize();
    void SolveCase(int Case);
    
    int main(int argc, char* argv[]) {
      CPPIO;
      int T = 1;
      std::cin >> T;
      for (int t = 1; t <= T; ++t) {
        SolveCase(t);
      }
      return 0;
    }
    
    void Initialize() {}
    
    int mod_;
    template <typename ValueType, typename SupperType>
    class Modular {
      static ValueType normalize(ValueType value) {
        if (value >= 0 && value < mod_)
          return value;
        value %= mod_;
        if (value < 0)
          value += mod_;
        return value;
      }
    
      static ValueType power(ValueType value, int64_t exponent) {
        ValueType result = 1;
        ValueType base = value;
        while (exponent) {
          if (exponent & 1)
            result = SupperType(result) * base % mod_;
          base = SupperType(base) * base % mod_;
          exponent >>= 1;
        }
        return result;
      }
    
     public:
      Modular(ValueType value = 0) : value_(normalize(value)) {}
    
      Modular(SupperType value) : value_(normalize(value % mod_)) {}
    
      ValueType value() const { return value_; }
    
      Modular inv() const { return Modular(power(value_, mod_ - 2)); }
    
      Modular power(int64_t exponent) const { return Modular(power(value_, exponent)); }
    
      friend Modular operator+(const Modular& lhs, const Modular& rhs) {
        ValueType result = lhs.value() + rhs.value() >= mod_ ? lhs.value() + rhs.value() - mod_
                                                             : lhs.value() + rhs.value();
        return Modular(result);
      }
    
      friend Modular operator-(const Modular& lhs, const Modular& rhs) {
        ValueType result = lhs.value() - rhs.value() < 0 ? lhs.value() - rhs.value() + mod_
                                                         : lhs.value() - rhs.value();
        return Modular(result);
      }
    
      friend Modular operator-(const Modular& lhs) {
        ValueType result = normalize(-lhs.value() + mod_);
        return result;
      }
    
      friend Modular operator*(const Modular& lhs, const Modular& rhs) {
        ValueType result = SupperType(1) * lhs.value() * rhs.value() % mod_;
        return Modular(result);
      }
    
      friend Modular operator/(const Modular& lhs, const Modular& rhs) {
        ValueType result = SupperType(1) * lhs.value() * rhs.inv().value() % mod_;
        return Modular(result);
      }
    
      std::string to_string() const { return std::to_string(value_); }
    
     private:
      ValueType value_;
    };
    using Mint = Modular<int, int64_t>;
    
    class Binom {
     private:
      std::vector<Mint> f, g;
    
     public:
      Binom(int n) {
        f.resize(n + 1);
        g.resize(n + 1);
    
        f[0] = Mint(1);
        for (int i = 1; i <= n; ++i)
          f[i] = f[i - 1] * Mint(i);
        g[n] = f[n].inv();
        for (int i = n - 1; i >= 0; --i)
          g[i] = g[i + 1] * Mint(i + 1);
      }
      Mint operator()(int n, int m) {
        if (n < 0 || m < 0 || m > n)
          return Mint(0);
        return f[n] * g[m] * g[n - m];
      }
    };
    
    using Mint = Modular<int, int64_t>;
    
    void SolveCase(int Case) {
      int p, a, b, s, g;
      std::cin >> p >> a >> b >> s >> g;
      mod_ = p;
    
      if (s == g) {
        std::cout << "0\n";
        return;
      }
    
      if (a == 0) {
        std::cout << (b == g ? 1 : -1) << "\n";
        return;
      }
    
      int M = std::sqrt(p);
    
      std::map<int, int> mp;
      Mint X(g);
      Mint c = Mint(a).inv(), d = Mint(a).inv() * Mint(-b);
      for (int i = 0; i < M; ++i) {
        if (!mp.count(X.value()))
          mp[X.value()] = i;
    
        X = X * c + d;
      }
    
      Mint Y(s);
      Mint A(1), B(0);
      for (int i = 0; i < M; ++i) {
        A = A * Mint(a);
        B = B * Mint(a) + Mint(b);
      }
      for (int i = 0; i <= p / M + 1; ++i) {
        if (mp.count(Y.value())) {
          int ans = i * M + mp[Y.value()];
          std::cout << ans << "\n";
          return;
        }
    
        Y = Y * A + B;
      }
    
      std::cout << "-1\n";
    }
    
    

    Ex - add 1

    记计数器的取值分别为 \(c_i\),定义当前状态为 \(k = \max_i(a_i - c_i)\)

    易得,存在 \(r\) 使得 \(a_r < k \le a_{r + 1}\) 。如果下一步选择的 \(i\) 满足 \(1 \le i \le r\) ,则状态会从 \(k\) 变为 \(k - 1\) ;如果 \(r + 1 \le i \le n\) ,则有状态会从 \(k\) 变为 \(a_i\)

    现在状态转移有了,就可以写出转移方程,假设 \(E_k\) 表示状态从 \(k\) 变为 \(0\) 的期望步数,则 \(E_{0} = 0\)\(E_{a_n}\) 即为答案。

    \[E_{k - 1} = \frac{1}{n}(rE_{k} + \sum_{j = r + 1}^{n} E_{A_j}) + 1 \tag{1} \]

    现在有个问题, \(E_k\) 可以从 \(E_x, x > k\) 推导得出,但是已知是 \(E_0 = 0\) ,方向对不上。记 \(F_k = E_{A_n} - E_k\) ,则有 \(F_{a_n} = 0\)\(F_0\) 即为答案。式(1)等式两边同乘 \(-1\) 再加上 \(E_{a_n}\) 可得

    \[rF_{k - 1} = nF_k + n - \sum_{j = r + 1}^{n} F_{a_j} \tag{2} \]

    依次计算 \(F_x, x = a_n, a_n - 1, \dots, 0\) 即可得到答案,但是 \(a_n \le {10}^{18}\),复杂度爆炸。

    注意到对于 \(a_r \le x < a_{r + 1}\)\(\sum_{j = r + 1}^{n} F_{a_j}\) 不变,记为 \(s_{r + 1}\) ,所以考虑将\(s_{r + 1}\)视为常数,然后把这一段的转移合并到一起。

    需要凑出一个 \(F_k\) 相关的 \(G_k\)\(G_k\) 这个式子已知某一项,可以快速地转移,例如 \(G_k\) 等比或者等差,但是由于 \(F_k\)\(F_{k - 1}\) 前的系数不同,所以等差不行。现在只剩等比的情况,然后式(2)中除了 \(F_x\) 相关的还有 \(n - s_{r + 1}\)\(G_k\) 和这个应该也有关系,然后就待定系数法有

    \[G_k = F_{k} + d(n - s_{r + 1})\\ r(F_{k-1} + d(n - s_{r + 1})) = n(F_k + d(n - s_{r + 1})) \tag{3} \]

    结合式(2)和(3)求出 \(d\),再带入(3)可得

    \[G_k = F_k + \frac{n - s_{r+1}}{n - r}\\ G_{k - 1} = \frac{n}{r} G_{k} \]

    \[F_{a_r} = (\frac{n}{r})^{a_{r + 1} - a_r} (F_{a_{r + 1}} + \frac{n - s_{r + 1}}{n - r}) - \frac{n - s_{r + 1}}{n - r} \]

    现在就可以依次求出 \(F_x, x = a_n, a_{n - 1}, \dots, a_1\),其中 \(F_{a_1} = F_0\) 即为答案。

    AC代码
    // Problem: Ex - add 1
    // Contest: AtCoder - TOYOTA MOTOR CORPORATION Programming Contest 2022(AtCoder Beginner Contest
    // 270) URL: https://atcoder.jp/contests/abc270/tasks/abc270_h Memory Limit: 1024 MB Time Limit:
    // 3000 ms
    //
    // Powered by CP Editor (https://cpeditor.org)
    
    #include <bits/stdc++.h>
    
    #define CPPIO std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
    
    #ifdef BACKLIGHT
    #include "debug.h"
    #else
    #define logd(...) ;
    #define ASSERT(x) ;
    #define serialize() std::string("")
    #endif
    
    using i64 = int64_t;
    using u64 = uint64_t;
    
    void Initialize();
    void SolveCase(int Case);
    
    int main(int argc, char* argv[]) {
      CPPIO;
      int T = 1;
      // std::cin >> T;
      for (int t = 1; t <= T; ++t) {
        SolveCase(t);
      }
      return 0;
    }
    
    void Initialize() {}
    
    template <typename ValueType, ValueType mod_, typename SupperType>
    class Modular {
      static ValueType normalize(ValueType value) {
        if (value >= 0 && value < mod_)
          return value;
        value %= mod_;
        if (value < 0)
          value += mod_;
        return value;
      }
    
      static ValueType power(ValueType value, int64_t exponent) {
        ValueType result = 1;
        ValueType base = value;
        while (exponent) {
          if (exponent & 1)
            result = SupperType(result) * base % mod_;
          base = SupperType(base) * base % mod_;
          exponent >>= 1;
        }
        return result;
      }
    
     public:
      Modular(ValueType value = 0) : value_(normalize(value)) {}
    
      Modular(SupperType value) : value_(normalize(value % mod_)) {}
    
      ValueType value() const { return value_; }
    
      Modular inv() const { return Modular(power(value_, mod_ - 2)); }
    
      Modular power(int64_t exponent) const { return Modular(power(value_, exponent)); }
    
      friend Modular operator+(const Modular& lhs, const Modular& rhs) {
        ValueType result = lhs.value() + rhs.value() >= mod_ ? lhs.value() + rhs.value() - mod_
                                                             : lhs.value() + rhs.value();
        return Modular(result);
      }
    
      friend Modular operator-(const Modular& lhs, const Modular& rhs) {
        ValueType result = lhs.value() - rhs.value() < 0 ? lhs.value() - rhs.value() + mod_
                                                         : lhs.value() - rhs.value();
        return Modular(result);
      }
    
      friend Modular operator-(const Modular& lhs) {
        ValueType result = normalize(-lhs.value() + mod_);
        return result;
      }
    
      friend Modular operator*(const Modular& lhs, const Modular& rhs) {
        ValueType result = SupperType(1) * lhs.value() * rhs.value() % mod_;
        return Modular(result);
      }
    
      friend Modular operator/(const Modular& lhs, const Modular& rhs) {
        ValueType result = SupperType(1) * lhs.value() * rhs.inv().value() % mod_;
        return Modular(result);
      }
    
      std::string to_string() const { return std::to_string(value_); }
    
     private:
      ValueType value_;
    };
    
    // using Mint = Modular<int, 1'000'000'007, int64_t>;
    using Mint = Modular<int, 998'244'353, int64_t>;
    
    class Binom {
     private:
      std::vector<Mint> f, g;
    
     public:
      Binom(int n) {
        f.resize(n + 1);
        g.resize(n + 1);
    
        f[0] = Mint(1);
        for (int i = 1; i <= n; ++i)
          f[i] = f[i - 1] * Mint(i);
        g[n] = f[n].inv();
        for (int i = n - 1; i >= 0; --i)
          g[i] = g[i + 1] * Mint(i + 1);
      }
      Mint operator()(int n, int m) {
        if (n < 0 || m < 0 || m > n)
          return Mint(0);
        return f[n] * g[m] * g[n - m];
      }
    };
    
    void SolveCase(int Case) {
      int n;
      std::cin >> n;
    
      std::vector<i64> a(n + 1);
      for (int i = 1; i <= n; ++i)
        std::cin >> a[i];
    
      Mint sr(0);
      Mint Fk(0);
      for (int i = n - 1; i >= 1; --i) {
        int r = i;
    
        Mint A = (Mint(n) / Mint(r)).power(a[i + 1] - a[i]);
        Mint B = (Mint(n) - Mint(sr)) / (Mint(n) - Mint(r));
    
        Fk = A * (Fk + B) - B;
        sr = sr + Fk;
      }
    
      std::cout << Fk.value() << "\n";
    }
    
    
  • 相关阅读:
    鱼眼相机畸变矫正资料
    异常值检测算法三:3sigma模型
    五:瑞芯微RV1109
    四:海思Hi3516CV500/Hi3516DV300
    三:瑞芯微OK3399-C开发板
    二:飞凌嵌入式FCU1201
    一:芯片概述
    六:大数据架构
    五:大数据架构回顾-LambdaPlus架构
    四:大数据架构回顾-IOTA架构
  • 原文地址:https://www.cnblogs.com/zengzk/p/16726958.html
Copyright © 2020-2023  润新知