有趣的思博套路题,想到了基本上加上个对线性基的理解就可以过了
首先考虑到这个把数分成两半的分别异或的过程不会改变某一位上(1)的总个数
因此我们求出所有数的(operatorname{xor}),然后从高到低枚举每一位的值,分情况讨论:
- 如果这一位是(1),那么显然分配完后必然使得(x_1,x_2)中一个是(0),一个是(1)
- 如果这一位是(0),如果不是全(0),那么必然可以构造方案让(x_1,x_2)两数都是(1)
比较一下我们优先使(x_1+x_2)最大,因此如果这一位是(0)就应该优先考虑
子集异或和最大怎么做,直接套线性基即可,这里其实就是改了下插入的优先级,让(0)位的先插入
求出(x_1+x_2)的最大值后我们尽量把(1)位上的(1)分给(x_2)即可,继续从高位到低位在线性基上查即可
CODE
#include<cstdio>
#include<cctype>
#define RI register int
#define CI const int&
#define Tp template <typename T>
using namespace std;
const int N=100005;
typedef long long LL;
int n; LL a[N],xrs;
class FileInputOutput
{
private:
static const int S=1<<21;
#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
char Fin[S],*A,*B;
public:
Tp inline void read(T& x)
{
x=0; char ch; while (!isdigit(ch=tc()));
while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
}
#undef tc
}F;
class Linear_Base
{
private:
static const int R=60;
LL bit[R+5];
public:
inline void insert(LL x)
{
RI i; for (i=R;~i;--i) if (!((xrs>>i)&1)&&((x>>i)&1))
{
if (!bit[i]) { bit[i]=x; return; } x^=bit[i];
}
for (i=R;~i;--i) if ((xrs>>i)&1&&((x>>i)&1))
{
if (!bit[i]) { bit[i]=x; return; } x^=bit[i];
}
}
inline LL query(LL ans=0)
{
RI i; for (i=R;~i;--i) if (!((xrs>>i)&1)&&!((ans>>i)&1)) ans^=bit[i];
for (i=R;~i;--i) if (((xrs>>i)&1)&&((ans>>i)&1)) ans^=bit[i]; return ans;
}
}LB;
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
RI i; for (F.read(n),i=1;i<=n;++i) F.read(a[i]),xrs^=a[i];
for (i=1;i<=n;++i) LB.insert(a[i]); return printf("%lld",LB.query()),0;
}