CF252A - Little Xor
题目
Little Xor - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
异或的部分性质:
- a ^ a = 0,a ^ 0 = a
- 异或具有交换律和结合律,a ^ b ^ c <=> (a ^ b) ^ c
思路
- 设序列为arr[n],ai表示下标为i的值,当 n = 6, 有 a0, a1, a2, a3, a4, a5
- 设xorPre[n]为异或前缀和,即xorPre[0] = a0, xorPre[1] = a0 ^ a1, xorPre[2] = a0 ^ a1 ^ a2 …
- [2, 4]区间的异或和为 xorSum = a2 ^ a3 ^ a4,因为 a0 ^ a1 ^ a0 ^ a1 = (a0 ^ a0) ^ (a1 ^ a1) = 0
- 可变换为 xorSum = a0 ^ a1 ^ a0 ^ a1 ^ a2 ^ a3 ^ a4 = (a0 ^ a1) ^ (a0 ^ a1 ^ a2 ^ a3 ^ a4)
- 即xorSum = xorPre[1] ^ xorPre[4]
- 拓展到任意区间[l, r], xorSum = xorPre[l - 1] ^ xorPre[r]
- 题目要求连续段中最大的异或和,我们枚举每一个区间[l, r]即可求出最大异或和
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 107;
// 异或前缀和数组
int xorPre[N];
int n;
int ans;
int main() {
cin >> n;
// 从下标1开始可以避免冗余的判断,当 i = 1 时 xorPre[1] = xorPre[0](0) ^ xorPre[1] = xorPre[1]
for (int i = 1; i <= n; i++) {
// 读入当前数值
cin >> xorPre[i];
// 与前一位的异或前缀和异或,得到当位异或和
xorPre[i] ^= xorPre[i - 1];
}
// 枚举左端点i
for (int i = 1; i <= n; i++) {
// 枚举右端点,并且j >= i区间才合法
for (int j = i; j <= n; j++) {
// 当前区间异或和与ans取最大值
ans = max(ans, xorPre[j] ^ xorPre[i - 1]);
}
}
// 输出答案
cout << ans << endl;
return 0;
}
复杂度分析
- 时间复杂度:O(n^2)
- 空间复杂度:O(n)