异或和一般都会想到01trie 或者线性基.
发现是在任意位置选取集合元素.
那么容易想到用线性基做.
考虑令s 等于所有数的异或和.
那么x1 ^ x2 = s
考虑怎么取得max(x1 + x2)且min(x1)
把s化为2进制.
对于s的某一位x,如果该位为0且有某一个数当前位为1,
则说明有偶数个数当前位为1,即可以把集合中s1s2分配进奇数个此位为1的数
那么此时的x1 x2都取到了最大值.
如果s的某一位x,如果该位为1.
则可以把所有当前位为1的都放入s2,
此时x1 不变,x2取到了最大...
最后求出x2的值,用s^x2即可求出x1
c++代码如下:
#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i = x; i <= y ;++ i)
#define repd(i,x,y) for(register int i = x; i >= y ; --i)
using namespace std;
typedef long long ll;
template<typename T>inline void read(T&x)
{
x = 0;char c;int sign = 1;
do { c = getchar(); if(c == '-') sign = -1; }while(!isdigit(c));
do { x = x * 10 + c - '0'; c = getchar(); }while(isdigit(c));
x *= sign;
}
ll a[101000],n,s,ans;
bool p[100];
void print(ll x)
{
int k[100],cnt = 0;
while(x)
{
k[++cnt] = x &1;
x >>= 1;
}
repd(i,cnt,1) printf("%d",k[i]);
puts("");
}
int main()
{
read(n);
rep(i,1,n) read(a[i]),s ^= a[i];
repd(i,63,0)
rep(j,1,n)
if(!p[j] && (a[j] & (1LL << i)) && !(s & (1LL << i))){
p[j] = 1;
if(!(ans & (1LL << i))) ans ^= a[j];
rep(k,1,n) if((a[k] & (1LL << i)) && !p[k]) a[k] ^= a[j];
break;
}
repd(i,63,0)
rep(j,1,n)
if(!p[j] && (a[j] & (1LL << i)) && (s & (1LL << i))){
p[j] = 1;
if(!(ans & (1LL << i))) ans ^= a[j];
rep(k,1,n) if((a[k] & (1LL << i)) && !p[k]) a[k] ^= a[j];
break;
}
cout << (s ^ ans) << endl;
return 0;
}