题解:AT_abc365_e [ABC365E] Xor Sigma Problem

· · 题解

三倍经验

P3917 异或序列

P9236 [蓝桥杯 2023 省 A] 异或和之和

类似题目

XOR on Segment

Sum of XOR Functions

题解

显然 a \bigoplus b \bigoplus b =a,所以考虑记录一个 pre 数组记录前缀异或和。

\begin{aligned} \sum_{i=1}^{i<n} \sum_{j=i+1}^{j\le n} \bigoplus_{k=i}^{k \le j} a_k &=\sum_{i=1}^{i\le n} \sum_{j=i}^{j\le n} \bigoplus_{k=i}^{k \le j} a_k - \sum_{i=1}^{i\le n} a_i \\ &= \sum_{i=1}^{i\le n} \sum_{j=i}^{j\le n} pre_{i} \bigoplus pre_{j} - \sum_{i=1}^{i\le n} a_i \end{aligned}

其中 \sum_{i=1}^{i\le n} a_i 可以 O(n) 计算,重点是计算前面这部分。

考虑把每个数按二进制拆分,逐位记录贡献,统计异或后二进制位为 1 的贡献。

时间复杂度 $O(n \log w)$。 ```cpp #include <bits/stdc++.h> using namespace std; #define N 200005 int n, a[N], pre[N]; void _main() { cin >> n; long long tot = 0; for (int i = 1; i <= n; i++) cin >> a[i], tot += a[i], pre[i] = pre[i - 1] ^ a[i]; long long res = 0; for (int i = 27; i >= 0; i--) { int s[2] = {0, 0}; for (int j = 1; j <= n; j++) { int u = pre[j - 1] >> i & 1, v = pre[j] >> i & 1; s[u]++; res += (1LL << i) * s[v ^ 1]; } } cout << res - tot; } signed main() { ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr); _main(); return 0; } ```