1 solutions
-
0
Guest MOD
-
0
我们可以把问题简化为逐位分析每个二进制位对最终异或和的贡献,因为异或运算的每一位是独立的,且加法在二进制下每一位的贡献可以单独计算。具体步骤如下:
. 统计每一位的出现次数
首先,对于数组中的每个数,我们观察它的每一个二进制位(从第 位,即最低位开始,到第 位,这里处理到 位足够)。 定义 为数组中所有数的第 位是 的数的个数。 例如,数组 (二进制是 和 ),第 位的 是 (只有 的第 位是 ),第 位的 是 ,第 位的 是 2(两个数的第 位都是 )。
. 对每个数计算异或和的贡献
对于数组中的每一个数 ,我们逐位分析它与数组中所有数的异或结果对总和的贡献: 假设当前分析第 位: 如果 的第 位是 : 当它与其他数 异或时,第 位为 的条件是 的第 位是 (因为 )。 这样的 共有 个,每个这样的异或结果在第 位贡献 ,对应的数值贡献是 (因为第 位的权重是 )。 如果 的第 位是 : 当它与其他数 异或时,第 位为 的条件是 的第 位是 (因为 )。 这样的 共有 个(总共有 n 个数,减去第 位是 的 个),对应的数值贡献是 。
. 累加每一位的贡献得到总和
对每个数 ,遍历所有 位( 到 ),根据上述规则计算每一位的贡献并累加,得到这个数与所有数的异或和。最后找出所有数中最大的异或和即可。
#include <bits/stdc++.h> using namespace std; #define int long long void solve() { int n; cin >> n; int arr[n+1]; vector<int> cnt(30, 0); for (int i = 1; i <= n; i++) { cin >> arr[i]; for (int j = 0; j < 30; j++) { cnt[j] += ((arr[i] >> j) & 1); } } int ans = 0; for (int i = 1; i <= n; i++) { int tot = 0; for (int j = 0; j < 30; j++) { bool f = ((arr[i] >> j) & 1); if (f) tot += (1 << j) * (n - cnt[j]); else tot += (1 << j) * cnt[j]; } ans = max(ans, tot); } cout << ans << "\n"; } signed main() { solve(); return 0; }
- 1
Information
- ID
- 1466
- Time
- 1000ms
- Memory
- 256MiB
- Difficulty
- 8
- Tags
- (None)
- # Submissions
- 86
- Accepted
- 10
- Uploaded By