Skip to the content.

:heavy_check_mark: test/yukicoder/1097.test.cpp

Depends on

Code

#define PROBLEM "https://yukicoder.me/problems/no/1097"
#include <bits/stdc++.h>

#include "library/algebra/group/Add.hpp"
#include "library/datastructure/Doubling.hpp"

using ll = long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n;
    std::cin >> n;
    Doubling<GroupAdd<ll>, 40> db(n);

    for (int i = 0; i < n; i++) {
        int a;
        std::cin >> a;
        db.add_arc(i, (i + a) % n, a);
    }

    int q;
    std::cin >> q;
    while (q--) {
        ll k;
        std::cin >> k;
        std::cout << db.calc(0, k).second << "\n";
    }
}
#line 1 "test/yukicoder/1097.test.cpp"
#define PROBLEM "https://yukicoder.me/problems/no/1097"
#include <bits/stdc++.h>

#line 2 "library/algebra/group/Add.hpp"
template<typename X>
struct GroupAdd {
  using value_type = X;
  static constexpr X op(const X &x, const X &y) noexcept { return x + y; }
  static constexpr void Rchop(X&x, const X&y){ x+=y; }
  static constexpr void Lchop(const X&x, X&y){ y+=x; }
  static constexpr X inverse(const X &x) noexcept { return -x; }
  static constexpr X power(const X &x, long long n) noexcept { return X(n) * x; }
  static constexpr X unit() { return X(0); }
  static constexpr bool commute = true;
};
#line 1 "library/datastructure/Doubling.hpp"
template <typename Monoid, int LOG> class Doubling {
    using X = typename Monoid::value_type;
    int n;
    bool is_prepared;

    using P = std::pair<int, X>;
    static constexpr P unit = {-1, Monoid::unit()};
    std::vector<std::vector<P>> DP;

    // a から 2^k 動く
    P k_move(const P &a, int k) {
        if (a.first == -1)
            return a;
        const auto [now, val] = a;
        const auto [nxt, cost] = DP[k][now];
        return {nxt, Monoid::op(val, cost)};
    }

    void build() {
        is_prepared = true;
        for (int k = 0; k < LOG - 1; k++)
            for (int v = 0; v < n; v++)
                DP[k + 1][v] = k_move(DP[k][v], k);
    }

  public:
    Doubling() = default;
    Doubling(int n) : n(n), is_prepared(false) {
        DP.assign(LOG, std::vector<P>(n, unit));
    }

    void add_arc(int from, int to, X x) {
        assert(!is_prepared);
        assert(-1 <= to and to < n);
        DP[0][from] = {to, x};
    }

    // [終点,値] 辺が出てない場所から移動する場合は -1 に着く
    P calc(int s, long long step) {
        assert(step <= (1LL << LOG));
        if (!is_prepared)
            build();

        P res{s, Monoid::unit()};
        for (int k = 0; step; k++, step >>= 1)
            if (step & 1)
                res = k_move(res, k);
        return res;
    }
};
#line 6 "test/yukicoder/1097.test.cpp"

using ll = long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n;
    std::cin >> n;
    Doubling<GroupAdd<ll>, 40> db(n);

    for (int i = 0; i < n; i++) {
        int a;
        std::cin >> a;
        db.add_arc(i, (i + a) % n, a);
    }

    int q;
    std::cin >> q;
    while (q--) {
        ll k;
        std::cin >> k;
        std::cout << db.calc(0, k).second << "\n";
    }
}
Back to top page