解题思路:
由于Nim游戏先手必胜的条件是每堆石子Xor和不为0,那么我们要求的即是:剩下最多的石子,且其不存在一个非空子集异或和为0。即求解极大线性无关组。。。
证明是个拟阵(不会证……)
因此只要把a[i]从大到小排序,依次贪心的添加到当前集合就可以了,若其可以成为一个基则剩下,否则拿走。(有点想kruskal啊)
关于高斯消元O(30n)求线性无关组的方法,可以看莫涛的《Xor方程组》。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int getint()
{
int i=0,f=1;char c;
for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());
if(c=='-')c=getchar(),f=-1;
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
const int N=105;
int n,a[N],base[30];
ll ans;
bool cmp(const int &a,const int &b)
{
return a>b;
}
int main()
{
//freopen("lx.in","r",stdin);
n=getint();
for(int i=1;i<=n;i++)a[i]=getint(),ans+=a[i];
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)
{
int cur=a[i];
for(int j=30;j>=0;j--)
if(cur&(1<<j))
{
if(base[j])cur^=base[j];
else{base[j]=cur;break;}
}
if(cur)ans-=a[i];
}
cout<<ans;
return 0;
}