测评会员优惠活动进行中 · 开通 VIP,有效期内测评不限次 VIP 优惠中 · 测评不限次 立即查看

A18254. 总异或和

填空题 较难

题目描述

总异或和

题目描述

给定长度为 n 的序列 A1,A2,,,,,An。

我们要计算所有数对 (i,j) 对应的 Ai + Aj 的总异或和。

即把所有满足 1 ≤ i,j ≤ n 的 Ai + Aj 依次进行异或,输出最终结果。

举例:当 n=3 时,计算式为

(A1+A1) (A1+A2) (A1+A3)

(A2+A1) (A2+A2) (A2+A3)

(A3+A1) (A3+A2) (A3+A3)

其中 表示按位异或运算。

输入格式

共两行:

第一行:一个正整数 n

第二行:n 个正整数,表示序列 A1,A2,,,,An

输出格式

输出一个整数,表示所有数对计算后的总异或值。

输入样例

3
2 12 27

输出样例

42

说明提示

1 ≤ n ≤ 106,1 ≤ Ai ≤ 109

参考答案

#include <iostream> #include <vector> #include <algorithm> using namespace std; typedef long long ll; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; vector<ll> a(n); for (int i = 0; i < n; ++i) cin >> a[i]; ll ans = 0; // 遍历每一位 0~30 for (int k = 0; k <= 30; ++k) { ll mod = 1LL << (k + 1); ll half = 1LL << k; vector<ll> rem; for (ll x : a) rem.push_back(x % mod); sort(rem.begin(), rem.end()); ll cnt = 0; int l = 0, r = n - 1; // 统计 r_i + r_j >= half 且 < mod for (; r >= 0; --r) { while (l < n && rem[l] + rem[r] < half) l++; cnt += n - max(l, r + 1); } // 统计 r_i + r_j >= mod + half l = 0, r = n - 1; for (; r >= 0; --r) { while (l < n && rem[l] + rem[r] < mod + half) l++; cnt += n - max(l, r + 1); } if (cnt % 2 == 1) ans |= half; } cout << ans << endl; return 0; }
上一题 下一题