結果

問題 No.619 CardShuffle
ユーザー kimiyukikimiyuki
提出日時 2017-12-19 20:27:27
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 837 ms / 3,000 ms
コード長 3,709 bytes
コンパイル時間 2,084 ms
コンパイル使用メモリ 207,200 KB
実行使用メモリ 36,096 KB
最終ジャッジ日時 2023-08-24 14:58:22
合計ジャッジ時間 17,667 ms
ジャッジサーバーID
(参考情報)
judge12 / judge11
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
4,380 KB
testcase_01 AC 2 ms
4,384 KB
testcase_02 AC 2 ms
4,380 KB
testcase_03 AC 2 ms
4,376 KB
testcase_04 AC 2 ms
4,384 KB
testcase_05 AC 2 ms
4,384 KB
testcase_06 AC 2 ms
4,380 KB
testcase_07 AC 2 ms
4,380 KB
testcase_08 AC 2 ms
4,376 KB
testcase_09 AC 2 ms
4,376 KB
testcase_10 AC 1 ms
4,380 KB
testcase_11 AC 2 ms
4,376 KB
testcase_12 AC 2 ms
4,380 KB
testcase_13 AC 2 ms
4,380 KB
testcase_14 AC 2 ms
4,380 KB
testcase_15 AC 2 ms
4,380 KB
testcase_16 AC 725 ms
35,820 KB
testcase_17 AC 728 ms
35,828 KB
testcase_18 AC 719 ms
36,096 KB
testcase_19 AC 720 ms
35,928 KB
testcase_20 AC 712 ms
35,780 KB
testcase_21 AC 837 ms
35,932 KB
testcase_22 AC 834 ms
35,832 KB
testcase_23 AC 829 ms
35,916 KB
testcase_24 AC 831 ms
35,884 KB
testcase_25 AC 834 ms
35,784 KB
testcase_26 AC 604 ms
35,808 KB
testcase_27 AC 603 ms
35,928 KB
testcase_28 AC 608 ms
35,932 KB
testcase_29 AC 601 ms
35,824 KB
testcase_30 AC 604 ms
35,756 KB
testcase_31 AC 1 ms
4,376 KB
testcase_32 AC 721 ms
35,920 KB
testcase_33 AC 723 ms
35,780 KB
testcase_34 AC 578 ms
35,828 KB
testcase_35 AC 106 ms
4,376 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>
#define REP(i, n) for (int i = 0; (i) < int(n); ++ (i))
#define REP_R(i, n) for (int i = int(n) - 1; (i) >= 0; -- (i))
using ll = long long;
using namespace std;

template <class Monoid>
struct segment_tree {
    typedef typename Monoid::underlying_type underlying_type;
    int n;
    vector<underlying_type> a;
    Monoid mon;
    segment_tree() = default;
    segment_tree(int a_n, underlying_type initial_value = Monoid().unit(), Monoid const & a_mon = Monoid()) : mon(a_mon) {
        n = 1; while (n < a_n) n *= 2;
        a.resize(2 * n - 1, mon.unit());
        fill(a.begin() + (n - 1), a.begin() + ((n - 1) + a_n), initial_value); // set initial values
        REP_R (i, n - 1) a[i] = mon.append(a[2 * i + 1], a[2 * i + 2]); // propagate initial values
    }
    void point_set(int i, underlying_type z) { // 0-based
        a[i + n - 1] = z;
        for (i = (i + n) / 2; i > 0; i /= 2) { // 1-based
            a[i - 1] = mon.append(a[2 * i - 1], a[2 * i]);
        }
    }
    underlying_type range_concat(int l, int r) { // 0-based, [l, r)
        underlying_type lacc = mon.unit(), racc = mon.unit();
        for (l += n, r += n; l < r; l /= 2, r /= 2) { // 1-based loop, 2x faster than recursion
            if (l % 2 == 1) lacc = mon.append(lacc, a[(l ++) - 1]);
            if (r % 2 == 1) racc = mon.append(a[(-- r) - 1], racc);
        }
        return mon.append(lacc, racc);
    }
};

constexpr int mod = 1e9 + 7;
constexpr int N = 4;
typedef array<ll, N> vec4;
typedef array<array<ll, N>, N> mat44;

mat44 operator * (mat44 const & a, mat44 const & b) {
    mat44 c = {};
    REP (k, N) REP (i, N) REP (j, N) (c[i][j] += a[i][k] * b[k][j]) %= mod;
    return c;
}
vec4 operator * (mat44 const & a, vec4 const & b) {
    vec4 c = {};
    REP (k, N) REP (i, N) (c[i] += a[i][k] * b[k]) %= mod;
    return c;
}
mat44 to_matrix(ll (& a)[N][N]) {
    mat44 b = {};
    REP (i, N) REP (j, N) b[i][j] = a[i][j];
    return b;
}
mat44 unit_matrix() {
    mat44 f = {};
    REP (i, N) f[i][i] = 1;
    return f;
}

struct matmul_monoid {
    typedef mat44 underlying_type;
    underlying_type unit() const { return unit_matrix(); }
    underlying_type append(underlying_type const & a, underlying_type const & b) const { return b * a; }
};

mat44 digit(int d) {
    ll f[N][N] = {
        { 1, 0,  0, 0 },
        { 0, 1,  0, 0 },
        { 0, d, 10, 0 },
        { 0, 0,  0, 1 },
    };
    return to_matrix(f);
}
mat44 mult() {
    ll f[N][N] = {
        { 1, 0, 0, 0 },
        { 0, 0, 1, 0 },
        { 0, 0, 0, 0 },
        { 0, 0, 0, 1 },
    };
    return to_matrix(f);
}
mat44 add(bool is_positive = true) {
    ll f[N][N] = {
        { 1, 0, 1, 0 },
        { 0, 0, 0, is_positive ? 1 : -1 },
        { 0, 0, 0, 0 },
        { 0, 0, 0, 1 },
    };
    return to_matrix(f);
}
int get_result(mat44 const & f) {
    vec4 x { { 0, 1, 0, 1 } };
    vec4 y = f * x;
    return (y[0] + y[2]) % mod;
}

int main() {
    // prepare
    int n; scanf("%d", &n);
    vector<char> c(n); REP (i, n) scanf(" %c", &c[i]);
    segment_tree<matmul_monoid> segtree(n);
    auto update = [&](int i) {
        mat44 a =
            c[i] == '+' ? add() :
            c[i] == '*' ? mult() :
            digit(c[i] - '0');
        segtree.point_set(i, a);
    };
    REP (i, n) update(i);
    // serve
    int q; scanf("%d", &q);
    while (q --) {
        char t; int x, y; scanf(" %c%d%d", &t, &x, &y); -- x; -- y;
        if (t == '!') {
            swap(c[x], c[y]);
            update(x);
            update(y);
        } else if (t == '?') {
            int result = get_result(segtree.range_concat(x, y + 1));
            printf("%d\n", result);
        }
    }
    return 0;
}
0