假如某一位有奇数个 \(1\),那么无论怎么拆分这一位都会有贡献。
那么先把这些贡献加起来,然后去除掉这些位。
发现剩下来的位都是偶数个 \(1\),也就意味着,无论怎么拆分,拆分出来的两个数的肯定相等。
那么就是求从一些数中选出若干个数,使得它们的异或和最大。
那么这个就是可以用线性基解决的。
时间复杂度 \(\mathcal O(n\log w)\)。
Code:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100005, M = 65;
int n;
ll a[N], B[M], cnt[M];
ll ans;
void insert(ll x) {
for (int i = 59; ~i; --i) if (x >> i & 1) {
if (B[i]) x ^= B[i];
else return B[i] = x, void();
}
}
ll query() {
ll res = 0;
for (int i = 59; ~i; --i)
res = max(res, res ^ B[i]);
return res;
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%lld", &a[i]);
for (int j = 59; ~j; --j)
if (a[i] >> j & 1) ++cnt[j];
}
for (int i = 59; ~i; --i) if (cnt[i] & 1) {
ans |= (1ll << i);
for (int j = 1; j <= n; ++j)
if (a[j] >> i & 1) a[j] ^= (1ll << i);
}
for (int i = 1; i <= n; ++i) insert(a[i]);
printf("%lld", query() * 2 + ans);
return 0;
}
标签:cnt,59,int,res,ll,ABC141F,--
From: https://www.cnblogs.com/Kobe303/p/16829938.html