제출 #1333624

#제출 시각아이디문제언어결과실행 시간메모리
1333624c4lIntergalactic ship (IZhO19_xorsum)C++20
0 / 100
303 ms4460 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int MOD = 1000000007;

int addmod(int a, int b){ a += b; if(a >= MOD) a -= MOD; return a; }
int submod(int a, int b){ a -= b; if(a < 0) a += MOD; return a; }
int mulmod(ll a, ll b){ return int((a*b) % MOD); }

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, q;
    if(!(cin >> n >> q)) return 0;
    vector<int> a(n+1);
    for(int i=1;i<=n;++i) cin >> a[i];

    struct Up { int l, r, m; };
    vector<Up> ups(q);
    for(int i=0;i<q;++i){
        cin >> ups[i].l >> ups[i].r >> ups[i].m;
    }

    // Precompute pow2[0..q]
    vector<int> pow2(q+1);
    pow2[0] = 1;
    for(int i=1;i<=q;++i) pow2[i] = addmod(pow2[i-1], pow2[i-1]);

    // cnt_pos[b][i] = số update (trong q) có bit b và che vị trí i
    const int BITS = 7; // 0..6
    vector<vector<int>> cnt_pos(BITS, vector<int>(n+2, 0));
    for(int b=0;b<BITS;++b){
        vector<int> diff(n+3, 0);
        for(auto &u : ups){
            if( (u.m >> b) & 1 ){
                diff[u.l] += 1;
                diff[u.r+1] -= 1;
            }
        }
        int cur = 0;
        for(int i=1;i<=n;++i){
            cur += diff[i];
            cnt_pos[b][i] = cur;
        }
    }

    // Hàm tiện: lấy bit ban đầu của a[pos] ở vị trí bit b
    auto bitOf = [&](int pos, int b)->int{
        return (a[pos] >> b) & 1;
    };

    // Kết quả: tính A = sum_S sum_i p_i^2   và B = sum_S sum_{i,j} p_i p_j
    // Cuối cùng ans = (n+1)*A - B (mod MOD)
    int A = 0;
    int B = 0;

    // Dùng một ma trận diff2D (n+2 x n+2) cho từng cặp (s,t)
    for(int s = 0; s < BITS; ++s){
        for(int t = 0; t < BITS; ++t){
            // diff2D: kích thước (n+3)x(n+3) để an toàn 1-based
            vector<vector<int>> diff2(n+3, vector<int>(n+3, 0));

            // Với mỗi update: nếu mask có cả bit s và bit t => cộng +1 vào rectangle [l..r] x [l..r]
            for(auto &u : ups){
                if( ((u.m >> s) & 1) && ((u.m >> t) & 1) ){
                    int l = u.l, r = u.r;
                    diff2[l][l] += 1;
                    diff2[r+1][l] -= 1;
                    diff2[l][r+1] -= 1;
                    diff2[r+1][r+1] += 1;
                }
            }

            // prefix 2D để lấy M11[x][y] = số updates che cả x và y và có cả 2 bit
            // first prefix on rows, then on cols (standard)
            for(int i=1;i<=n+1;++i){
                for(int j=1;j<=n+1;++j){
                    diff2[i][j] += diff2[i-1][j] + diff2[i][j-1] - diff2[i-1][j-1];
                }
            }
            // Now diff2[x][y] for 1..n is M11

            // Hãy duyệt mọi x,y và tính H = số tập con S sao cho sau khi apply S:
            // bit s ở x = 1 và bit t ở y = 1.
            // Quy tắc: xác định c11, c10, c01, c00; từ đó xác định rank và membership của target.
            int pow_s_t = (int)((1LL << s) % MOD); // careful: (1<<s) safe since s<=6
            // but (1<<s) fits in int. use pow2 precomp for powers of 2 by exponent.
            int two_s = (1<<s);
            int two_t = (1<<t);
            int two_st = ((1<<s) * 1LL * (1<<t)) % MOD; // 2^{s+t} modulo up to small

            // Better compute coef = 2^{s+t} mod MOD
            int coef = 1;
            // compute 2^{s+t} via pow2 of small exponent (s+t <= 12)
            int expsmall = s + t;
            for(int k=0;k<expsmall;++k) coef = addmod(coef, coef); // coef *= 2^expsmall
            // But above doubles coef expsmall times from 1 -> 2^{expsmall}. That's fine.

            // Alternatively faster: coef = (1<<expsmall) % MOD; but (1<<12)=4096 safe.
            coef = (1 << expsmall) % MOD;

            for(int x=1;x<=n;++x){
                for(int y=1;y<=n;++y){
                    int c11 = diff2[x][y];
                    int c10 = cnt_pos[s][x] - c11;
                    int c01 = cnt_pos[t][y] - c11;
                    int c00 = q - (c11 + c10 + c01);

                    bool has10 = (c10 > 0);
                    bool has01 = (c01 > 0);
                    bool has11 = (c11 > 0);
                    int types = (has10?1:0) + (has01?1:0) + (has11?1:0);
                    int rank = min(2, types);

                    int Tx = 1 - bitOf(x, s); // cần parity toggles = 1 - initial bit
                    int Ty = 1 - bitOf(y, t);

                    int H = 0;
                    if(rank == 0){
                        if(Tx == 0 && Ty == 0) H = pow2[q]; // mọi update phải đóng góp 0 => chỉ có (0,0) vectors
                        else H = 0;
                    } else if(rank == 1){
                        // tìm vector v hiện hữu
                        int vx = 0, vy = 0;
                        if(has10){ vx = 1; vy = 0; }
                        else if(has01){ vx = 0; vy = 1; }
                        else { vx = 1; vy = 1; }
                        // T phải là 0 hoặc v
                        if( (Tx == 0 && Ty == 0) || (Tx == vx && Ty == vy) ){
                            H = pow2[q-1];
                        } else H = 0;
                    } else { // rank == 2
                        // span = whole space => mọi T được
                        H = pow2[q-2];
                    }

                    if(H == 0) continue;

                    // đóng góp vào A và B
                    // A += 2^{s+t} * H * (n - max(x,y) + 1)
                    // B += 2^{s+t} * H * (n - x + 1) * (n - y + 1)
                    int multA = (n - max(x,y) + 1);
                    int multB1 = (n - x + 1);
                    int multB2 = (n - y + 1);

                    int term = mulmod(coef, H);
                    int addA = mulmod(term, multA % MOD);
                    int addB = mulmod(term, (1LL * multB1 % MOD) * (multB2 % MOD) % MOD);

                    A = addmod(A, addA);
                    B = addmod(B, addB);
                }
            }

            // free diff2 by letting it go out of scope at next iteration
        }
    }

    // answer = (n+1) * A - B (mod)
    int ans = mulmod((n+1) % MOD, A);
    ans = submod(ans, B);
    cout << ans << "\n";
    return 0;
}
#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...