小红的异或之和

思路分析

拿到这道题,我们首先要搞清楚:矩阵 的所有子矩阵之和到底怎么算?

暴力枚举所有子矩阵肯定不行。那我们换个角度想:每个元素 会被多少个子矩阵包含?

一个子矩阵由左上角 和右下角 确定。如果 被包含,需要

用 1-indexed 来算:

  • 种选法(), 种选法(
  • 种选法, 种选法

所以 的贡献次数为

接下来,注意到贡献次数可以行列分离:定义行权重 ,列权重 ,那么:

$$

由于 ,异或结果只有两种情况:

  • ,对应 的列
  • ,对应 的列

因此我们预处理出 ,然后对每一行

  • ,贡献为
  • ,贡献为

这样总时间复杂度就从 降到了

代码

#include <bits/stdc++.h>
using namespace std;

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

    const long long MOD = 1e9 + 7;
    int n;
    cin >> n;

    vector<int> a(n), b(n);
    for(int i = 0; i < n; i++) cin >> a[i];
    for(int i = 0; i < n; i++) cin >> b[i];

    // col_weight[j] = (j+1) * (n-j) for 0-indexed
    long long S_col = 0, S_col_1 = 0;
    for(int j = 0; j < n; j++){
        long long w = (long long)(j+1) * (n-j) % MOD;
        S_col = (S_col + w) % MOD;
        if(b[j] == 1){
            S_col_1 = (S_col_1 + w) % MOD;
        }
    }

    long long S_col_0 = (S_col - S_col_1 + MOD) % MOD;

    long long ans = 0;
    for(int i = 0; i < n; i++){
        long long rw = (long long)(i+1) * (n-i) % MOD;
        if(a[i] == 1){
            ans = (ans + rw % MOD * S_col_0 % MOD) % MOD;
        } else {
            ans = (ans + rw % MOD * S_col_1 % MOD) % MOD;
        }
    }

    cout << ans << endl;
    return 0;
}
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        final long MOD = 1000000007L;
        int n = sc.nextInt();
        int[] a = new int[n], b = new int[n];
        for (int i = 0; i < n; i++) a[i] = sc.nextInt();
        for (int i = 0; i < n; i++) b[i] = sc.nextInt();

        long sCol = 0, sCol1 = 0;
        for (int j = 0; j < n; j++) {
            long w = (long)(j + 1) * (n - j) % MOD;
            sCol = (sCol + w) % MOD;
            if (b[j] == 1) sCol1 = (sCol1 + w) % MOD;
        }
        long sCol0 = (sCol - sCol1 + MOD) % MOD;

        long ans = 0;
        for (int i = 0; i < n; i++) {
            long rw = (long)(i + 1) * (n - i) % MOD;
            if (a[i] == 1) {
                ans = (ans + rw * sCol0 % MOD) % MOD;
            } else {
                ans = (ans + rw * sCol1 % MOD) % MOD;
            }
        }
        System.out.println(ans);
    }
}

复杂度分析

  • 时间复杂度,两次遍历数组即可。
  • 空间复杂度,存储输入数组。