BZOJ 3105: [cqoi2013]新Nim游戏(线性基)
解题思路
\(nim\)游戏先手必胜的条件是异或和不为\(0\),也就是说第一个人拿走了若干堆后不管第二个人怎么拿都不能将剩余堆的异或和变成\(0\)。考虑线性基,其实就是每个数对线性基都有贡献,任何一个数不会被线性表出,要使拿走元素最少,考虑贪心,将所有数字从大到小依次尝试插入线性基,插入失败就累计到答案。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=105;
typedef long long LL;
int b[35],a[N],k;
LL ans;
inline bool cmp(int x,int y){
return x>y;
}
inline void Insert(int x){
int pre=x;
for(int i=30;~i;i--)
if(x&(1<<i)) {
if(!b[i]) {b[i]=x;return;}
x^=b[i];
}
ans+=pre;
}
int main(){
scanf("%d",&k);
for(int i=1;i<=k;i++) scanf("%d",&a[i]);
sort(a+1,a+1+k,cmp);
for(int i=1;i<=k;i++) Insert(a[i]);
printf("%lld\n",ans);
return 0;
}