[CQOI2013] 新Nim游戏
kang了一下Nim游戏之后豁然开朗。
Nim游戏的结论十分简介,当且仅当一开始所有堆的石头数异或和不为0时先手必胜。
然后再思考这道题何时先手必胜。问题转化成要让对方使用本题特权却无法使得石头数异或和为0,我们应该如何使用特权。显然我们使用特权后应该留下的是一个不存在异或和为0的子集合的石头集合,而这是线性基擅长的。
为了使得拿走的尽量少,就是要让留下的尽量多,考虑从大到小插入元素即可。
#include<cstdio>
#include<algorithm>
#define zczc
#define ll long long
using namespace std;
const int N=105;
const int S=32;
inline void read(int &wh){
wh=0;int f=1;char w=getchar();
while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
wh*=f;return;
}
int m,a[N],s[S];
ll ans;
inline bool cmp(int s1,int s2){
return s1>s2;
}
signed main(){
#ifdef zczc
freopen("in.txt","r",stdin);
#endif
read(m);
for(int i=1;i<=m;i++)read(a[i]);
sort(a+1,a+m+1,cmp);
for(int i=1,now=0;i<=m;i++){
ans+=(now=a[i]);
for(int j=S-1;j>=0;j--){
if((a[i]&(1<<j))==0)continue;
if(s[j])a[i]^=s[j];
else{ans-=now;s[j]=a[i];break;}
}
}
printf("%lld",ans);
return 0;
}
一如既往,万事胜意