题目链接
题意
给定(n)个数,取其中的一个子集,使得异或和最大,求该最大的异或和。
思路
先求得线性基。
则求原(n)个数的所有子集的最大异或和便可转化成求其线性基的子集的最大异或和。
因为线性基可排列成一个行简化梯形矩阵,每一行的最左边的(1)的位置递增,且该(1)所在列的其余元素全为(0).
故显见最大值即为将全部异或起来。
Code
#include <stdio.h>
#include <string.h>
#define maxl 60
using namespace std;
typedef long long LL;
struct LinearBasis {
LL a[maxl+1];
LinearBasis() { memset(a, 0, sizeof(a)); }
void insert(LL t) {
for (int i = maxl; i >= 0; --i) {
if (!(t >> i & 1)) continue;
if (a[i]) t ^= a[i];
else {
for (int j = 0; j < i; ++j) if (t >> j & 1) t ^= a[j];
for (int j = i+1; j <= maxl; ++j) if (a[j] >> i & 1) a[j] ^= t;
a[i] = t;
return;
}
}
}
LL sum() {
LL ret = 0;
for (int i = 0; i <= maxl; ++i) ret ^= a[i];
return ret;
}
};
int main() {
int n;
scanf("%d", &n);
LinearBasis lb;
for (int i = 0; i < n; ++i) {
LL x;
scanf("%lld", &x);
lb.insert(x);
}
printf("%lld
", lb.sum());
return 0;
}