[CQOI2013] 新Nim游戏

link

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;
}
posted @ 2022-02-19 16:01  Feyn618  阅读(32)  评论(0编辑  收藏  举报