제출 #1325518

#제출 시각아이디문제언어결과실행 시간메모리
1325518zwezdinvIntergalactic ship (IZhO19_xorsum)C++20
100 / 100
971 ms21132 KiB
#include <bits/stdc++.h>

using u32 = uint32_t;
using u64 = uint64_t;

struct Montgomery {
    u32 mod, mod_inv, one;

    Montgomery(u32 mod) : mod(mod), mod_inv(1) {
        for (int i = 0; i < 5; ++i) {
            mod_inv *= 2 - mod * mod_inv;
        }
        one = (u64(1) << 32) % mod;
    }
    u32 norm(u32 x) const {
        return x < x - mod ? x : x - mod;
    }
    u32 transform(u32 x) const {
        return ((u64)x << 32) % mod;
    }
    u32 reduce(u64 x) const {
        u32 m = (u32(x) * mod_inv * u64(mod)) >> 32;
        return norm((x >> 32) + mod - m);
    }
    u32 add(u32 x, u32 y) const {
        return x + y >= mod ? x + y - mod : x + y;
    }
    u32 sub(u32 x, u32 y) const {
        return x >= y ? x - y : x + mod - y;
    }
    u32 mul(u32 x, u32 y) const {
        return reduce((u64)x * y);
    }
    u32 power(u32 x, u64 y) {
        u32 ret = one;
        for (; y; y >>= 1, x = mul(x, x)) {
            if (y & 1) ret = mul(ret, x);
        }
        return ret;
    }
    u32 inv(u32 x) {
        return power(x, mod - 2);
    }
    u32 div(u32 x, u32 y) {
        return mul(x, inv(y));
    }
};
const int mod = 1e9 + 7;
Montgomery mt(mod);

const int N = 1001;
int n, v[N], mask[4][N][N];

void init() {
    for (int c = 0; c < 4; ++c) {
        for (int i = 0; i <= n; ++i) {
            for (int j = 0; j <= n; ++j) {
                mask[c][i][j] = 0;
            }
        }
    }
}
void apply(int c, int lx, int rx, int ly, int ry) {
    if (lx > rx || ly > ry) return;
    ++rx, ++ry;
    ++mask[c][lx][ly], ++mask[c][rx][ry];
    --mask[c][lx][ry], --mask[c][rx][ly];
}
void build() {
    for (int c = 0; c < 4; ++c) {
        for (int i = 0; i <= n; ++i) {
            for (int j = 0; j <= n; ++j) {
                if (i > 0) mask[c][i][j] += mask[c][i - 1][j];
                if (j > 0) mask[c][i][j] += mask[c][i][j - 1];
                if (i > 0 && j > 0) mask[c][i][j] -= mask[c][i - 1][j - 1];
            }
        }
    }
}

const int Q = 1e6;
int precalc[16][4];
int dp[4], ndp[4], pw2[Q];

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

    pw2[0] = mt.one;
    for (int i = 1; i < Q; ++i) pw2[i] = mt.add(pw2[i - 1], pw2[i - 1]);


    std::cin >> n;
    for (int i = 0; i < n; ++i) std::cin >> v[i];
    int q;
    std::cin >> q;
    std::vector<std::array<int, 3>> ques(q);
    for (auto& [l, r, x] : ques) {
        std::cin >> l >> r >> x;
        --l, --r;
    }
    for (int mask = 0; mask < 1 << 4; ++mask) {
        int s = q - __builtin_popcount(mask);
        if (s < 0) continue;
        std::fill(dp, dp + 4, 0);
        dp[0] = pw2[s];
        for (int i = 0; i < 4; ++i) {
            if (~mask >> i & 1) continue;
            std::copy(dp, dp + 4, ndp);
            for (int j = 0; j < 4; ++j) {
                ndp[j] = mt.add(ndp[j], dp[j ^ i]);
            }
            std::copy(ndp, ndp + 4, dp);
        }
        std::copy(dp, dp + 4, precalc[mask]);
    }
    int ans = 0;
    for (int a = 0; a < 7; ++a) {
        for (int b = a; b < 7; ++b) {
            init();
            for (auto [l, r, x] : ques) {
                int ca = x >> a & 1, cb = x >> b & 1;
                apply(0, 0, l - 1, 0, l - 1);
                apply(ca, l, r, 0, l - 1);
                apply(0, r + 1, n - 1, 0, l - 1);
                apply(2 * cb, 0, l - 1, l, r);
                apply(ca + 2 * cb, l, r, l, r);
                apply(2 * cb, r + 1, n - 1, l, r);
                apply(0, 0, l - 1, r + 1, n - 1);
                apply(ca, l, r, r + 1, n - 1);
                apply(0, r + 1, n - 1, r + 1, n - 1);
            }
            build();
            for (int i = 0; i < n; ++i) {
                for (int j = 0; j < n; ++j) {
                    int ca = v[i] >> a & 1, cb = v[j] >> b & 1;
                    int msk = 0;
                    for (int k = 0; k < 4; ++k) {
                        int cnt = mask[k][i][j];
                        if (cnt > 0) msk |= 1 << k;
                    }
                    int coef = mt.mul(mt.mul(mt.transform(std::min(i, j) + 1), mt.transform(n - std::max(i, j))), pw2[a + b]);
                    if (a != b) coef = mt.add(coef, coef);
                    ans = mt.add(ans, mt.mul(precalc[msk][3 - ca - 2 * cb], coef));
                }
            }
        }
    }
    std::cout << mt.reduce(ans);
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...