QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#318666#7561. Digit DPIsrothyWA 702ms22520kbC++236.3kb2024-01-31 16:42:212024-01-31 16:42:21

Judging History

你现在查看的是最新测评结果

  • [2024-01-31 16:42:21]
  • 评测
  • 测评结果:WA
  • 用时:702ms
  • 内存:22520kb
  • [2024-01-31 16:42:21]
  • 提交

answer

#include <algorithm>
#include <cassert>
#include <cstdint>
#include <iostream>

constexpr int mod = 998244353;
constexpr int M = 105;

using int128_t = __int128;
using uint128_t = unsigned __int128;

template<typename T>
T power(T x, T k) {
    T res(1);
    for (; k; k >>= 1) {
        if (k & 1) {
            res = res * x % mod;
        }
        x = x * x % mod;
    }
    return res;
}

constexpr int64_t c3(int64_t n) {
    return static_cast<int64_t>((int128_t(n) * (n - 1) * (n - 2) / 6 % mod));
}

constexpr int64_t c2(int64_t n) {
    return static_cast<int64_t>(n * (n - 1) / 2 % mod);
}

struct data {
    int s0, s1, s2, s3;
    explicit data(int s0 = 0, int s1 = 0, int s2 = 0, int s3 = 0)
        : s0(s0), s1(s1), s2(s2), s3(s3) {}
    data add(int64_t x) const {
        auto x2 = x * x % mod;
        auto x3 = x2 * x % mod;
        return data(
            s0,
            static_cast<int>((s1 + s0 * x) % mod),
            static_cast<int>((s2 + x * (s0 - 1) % mod * s1 + x2 * c2(s0)) % mod),
            static_cast<int>(
                (s3 + x * (s0 - 2) * s2 + x2 * c2(s0 - 1) % mod * s1 + x3 * c3(s0)) % mod
            )
        );
    }
    data mul(int64_t x) const {
        auto x2 = x * x % mod;
        auto x3 = x2 * x % mod;
        return data(
            s0,
            static_cast<int>((s1 * x) % mod),
            static_cast<int>((s2 * x2) % mod),
            static_cast<int>((s3 * x3) % mod)
        );
    }
};

data merge(const data &l, const data &r) {
    return data(
        (l.s0 + r.s0) % mod,
        (l.s1 + r.s1) % mod,
        static_cast<int>((l.s2 + r.s2 + (int64_t) l.s1 * r.s1) % mod),
        static_cast<int>((l.s3 + r.s3 + (int64_t) l.s1 * r.s2 + (int64_t) l.s2 * r.s1) % mod)
    );
}
data s[M];
int64_t a[M];
int n;


struct tree {
    data v{};
    tree *ls, *rs;
    int lazy;
    void push_up() {
        v = merge(ls->v, rs->v);
    }
    tree(data v, tree *ls, tree *rs) : v(v), ls(ls), rs(rs), lazy(0) {}
    tree(int64_t prefix, int depth) : v(s[depth].add(prefix)), ls(nullptr), rs(nullptr), lazy(0){};
    void push_down(int64_t pl, int64_t pr, int depth) {
        if (!ls) {
            ls = new tree(pl, depth);
        }
        if (!rs) {
            rs = new tree(pr, depth);
        }
        if (!lazy) {
            return;
        }
        ls->v = ls->v.add(lazy);
        ls->lazy = (ls->lazy + lazy) % mod;
        rs->v = rs->v.add(lazy);
        rs->lazy = (rs->lazy + lazy) % mod;
        lazy = 0;
    }
};

auto query(
    tree *&p, uint128_t l, uint128_t r, uint128_t _l, uint128_t _r, int64_t prefix, int depth
) {
    /* if (!p) { */
    /*     p = new tree(prefix, depth); */
    /* } */
    if (l == _l && r == _r) {
        return p->v;
    }
    auto pl = prefix;
    auto pr = (prefix + a[depth]) % mod;
    p->push_down(pl, pr, depth + 1);
    auto mid = (l + r) >> 1;
    if (_r <= mid) {
        return query(p->ls, l, mid, _l, _r, pl, depth + 1);
    }
    if (_l > mid) {
        return query(p->rs, mid + 1, r, _l, _r, pr, depth + 1);
    }
    return merge(
        query(p->ls, l, mid, _l, mid, pl, depth + 1),
        query(p->rs, mid + 1, r, mid + 1, _r, pr, depth + 1)
    );
}

std::ostream &operator<<(std::ostream &os, uint128_t x) {
    if (x <= 9) {
        os << (int) x;
        return os;
    }
    os << (x / 10) << (int) (x % 10);
    return os;
}

void update(
    tree *&p,
    uint128_t l,
    uint128_t r,
    uint128_t _l,
    uint128_t _r,
    int64_t prefix,
    int depth,
    int64_t x
) {
    /* if (!p) { */
    /*     p = new tree(prefix, depth); */
    /* } */
    /* assert(p); */
    /* std::cerr << l << " " << r << " " << _l << " " << _r << " " << prefix << " " << depth */
    /*           << std::endl; */
    if (l == _l && r == _r) {
        p->v = p->v.add(x);
        p->lazy = static_cast<int>((p->lazy + x) % mod);
        return;
    }
    auto pl = prefix;
    auto pr = (prefix + a[depth]) % mod;
    /* puts("wow"); */
    p->push_down(pl, pr, depth + 1);
    auto mid = (l + r) >> 1;
    if (_r <= mid) {
        update(p->ls, l, mid, _l, _r, pl, depth + 1, x);
    } else if (mid < _l) {
        update(p->rs, mid + 1, r, _l, _r, pr, depth + 1, x);
    } else {
        update(p->ls, l, mid, _l, mid, pl, depth + 1, x);
        update(p->rs, mid + 1, r, mid + 1, _r, pr, depth + 1, x);
    }
    p->push_up();
}

int main() {
    int n, q;
    scanf("%d%d", &n, &q);
    for (int i = 0; i < n; ++i) {
        scanf("%lld", a + i);
    }
    std::reverse(a, a + n);
    s[n] = data(1, 0);
    for (int i = n - 1; i >= 0; --i) {
        s[i] = merge(s[i + 1].add(a[i]), s[i + 1]);
    }
    /* { */
    /*     auto t = s[n].add(a[n - 1]); */
    /*     fprintf(stderr, "t = %d %d %d %d\n", t.s0, t.s1, t.s2, t.s3); */
    /* } */
    /* { */
    /*     auto f = [&](int x) { */
    /*         int64_t res = 1; */
    /*         for (int i = 0; i < n; ++i) { */
    /*             if (x >> i & 1) { */
    /*                 res = res * a[i] % mod; */
    /*             } */
    /*         } */
    /*         return res; */
    /*     }; */
    /*     int64_t sum = 0; */
    /*     for (int i = 0; i < 1 << n; ++i) { */
    /*         for (int j = i + 1; j < 1 << n; ++j) { */
    /*             for (int k = j + 1; k < 1 << n; ++k) { */
    /*                 sum = (sum + f(i) + f(j) + f(k)) % mod; */
    /*             } */
    /*         } */
    /*     } */
    /*     fprintf(stderr, "sum = %lld\n", sum); */
    /*     for (int i = 0; i <= n; ++i) { */
    /*         fprintf(stderr, "s[%d] = %d %d %d %d\n", i, s[i].s0, s[i].s1, s[i].s2, s[i].s3); */
    /*     } */
    /* } */
    auto root = new tree(0, 0);
    while (q--) {
        int op;
        char sl[200], sr[200];
        scanf("%d%s%s", &op, sl, sr);
        uint128_t l = 0, r = 0;
        for (int i = 0; i < n; ++i) {
            l = l << 1 | sl[i] - '0';
            r = r << 1 | sr[i] - '0';
        }
        if (op == 1) {
            int x;
            scanf("%d", &x);
            update(root, 0, ((uint128_t) 1 << n) - 1, l, r, 0, 0, x);
        } else {
            printf("%d\n", (query(root, 0, ((uint128_t) 1 << n) - 1, l, r, 0, 0).s3 + mod) % mod);
        }
    }
    return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 0ms
memory: 3828kb

input:

3 3
1 2 4
2 000 111
1 010 101 1
2 000 111

output:

1960
3040

result:

ok 2 number(s): "1960 3040"

Test #2:

score: 0
Accepted
time: 0ms
memory: 3836kb

input:

2 2
1 1
2 00 10
2 00 11

output:

0
2

result:

ok 2 number(s): "0 2"

Test #3:

score: -100
Wrong Answer
time: 702ms
memory: 22520kb

input:

99 49952
470888 74578 802746 396295 386884 721198 628655 722503 207868 647942 87506 792718 761498 917727 843338 908043 952768 268783 375312 414369 319712 96230 277106 168102 263554 936674 246545 667941 198849 268921 191459 436316 134606 802932 515506 837311 465964 394766 17626 650419 984050 790137 4...

output:

591354622
640451152
325661507
580867983
195134189
977690611
229653421
515543640
456234713
277404887
64601170
414890
378873553
196181462
365184913
570079294
127018203
356663707
403036453
550290737
464255545
844501038
323052431
215084102
173581973
14808535
961784547
114932699
152892612
629501135
95173...

result:

wrong answer 1st numbers differ - expected: '413449847', found: '591354622'