- 题解
异或和
- @ 2026-8-29 21:33:03
这道题是一道经典的**按位贡献(位运算拆分)**问题。
解题思路:
异或运算(XOR)的性质是:相同为0,不同为1。
我们可以分开计算二进制每一位对答案的贡献。 对于第 位(权值为 ):
- 设数组中这一位为 1 的数字个数为
cnt1 - 那么这一位为 0 的数字个数即为
cnt0 = N - cnt1 - 要使两个数异或后第 k 位为 1,必须一个数是 0,另一个数是 1。
- 能够组成这样不同数对的组合数为
cnt0 * cnt1。
因此,第 位对总和的贡献为:。 将二进制每一位的贡献累加起来,就是最终答案。
#include <bits/stdc++.h>
#define int long long
using namespace std;
int T = 1;
const int N = 3e5 + 1, B = 60;//坏习惯,考场上记得多加点
const int MOD = 1e9 + 7;
int n;
int arr[N];
//慢速乘(也叫快速乘),防止溢出,顺便装一下,直接使用乘即可
int MulSlowly(int a, int b) {
if (a == 0 || b == 0) return 0;
int ans = 0;
while (b) {
if (b & 1) {
ans = (ans + a) % MOD;
}
a = (a + a) % MOD;
b >>= 1;
}
return ans;
}
void Solve() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> arr[i];
}
int ans = 0;
for (int k = 0; k <= B; k++) {
int cnt1 = 0;
for (int j = 1; j <= n; j++) {
if ((1ll << k) & arr[j]) {
cnt1++;
}
}
int cnt0 = n - cnt1;
ans = (ans + MulSlowly(MulSlowly(cnt0, cnt1), (1ll << k))) % MOD;
}
cout << ans;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
while (T--) {
Solve();
}
return 0;
}
1 条评论
-
张泊文 ⛰️ 登峰造极 LV 8 @ 2026-8-31 2:24:34题解大佬
- 1