我们第一次拿完后,要使得剩下的火柴中不存在异或和为0的子集,否则对方会将先手必败的状态留给我们。
因此我们需要寻求极大的线性无关组,答案即为总和减去极大线性无关组的权值和。
显然存在线性无关组,因此必然存在解。
那么如何求解极大线性无关组呢?
我们能够证明这是一个拟阵,因此只需要从大到小排序,依次贪心的添加到当前集合就可以了。
每次我们记下一个数的条件是:这个数第i位前都是0,第i位才是1。这样就类似于高斯消元里面的再到一个位置数。然后开始消。
消到后面这个数前k位都是0也就是前k个未知数已经消去。把第k+1位数作为下次消的元。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long sint;
int n,a[1000],save[1000],que[1000],ins[1000],top;
sint sum,ans;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&save[i]);
sort(save+1,save+1+n);
for(int i=1;i<=n;i++)
{
a[i]=save[i];
sum+=a[i];
}
for(int i=n;i;i--)
{
for(int j=30;j>=0;j--)
{
if((a[i]>>j)&1)
{
if(!ins[j])
{
ins[j]=i;
break;
}
else
{
a[i]^=a[ins[j]];
}
}
}
if (a[i])
ans += save[i];
}
if(ans) printf("%lld\n",sum-ans);
else printf("-1");
return 0;
}