[CQOI2013]新Nim游戏

题目

刚开始看成不能取走一整堆吓死我了

还有这出题人的语文水平,一回合不是两个玩家操作各一次吗?

考虑一下Nim游戏里面临的必败条件

\[\bigoplus \sum_{i=1}^nres_i=0 \]

也就是所有数的异或和为\(0\)

从线性基的角度来考虑这个问题

我们可以把某一个部分\(S\)搞出来

就是

\[\bigoplus \sum_{i\in S}res_i=\bigoplus \sum_{i\notin S}res_i \]

也就是说有一些元素无法插入线性基里去

作为第一个操作者我们自然不能让这样的情况发生,为了防止第二个人搞一些破坏我们必须把所有无法插入线性基的都取走

还要让取走的和最小,我们贪心先插入大的就好了

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define re register
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read() {
	int x=0;char c=getchar();while(c<'0'||c>'9') c=getchar();
	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
int n;
int a[105],lb[105];
inline int cmp(int A,int B) {return A>B;}
inline int ins(int x) {
	for(re int j=31;j>=0;--j) 
		if(x>>j&1) {
			if(!lb[j]) {lb[j]=x;return 1;}
			x^=lb[j];
		}
	return 0;
}
int main()
{
	n=read();
	for(re int i=1;i<=n;i++) a[i]=read();
	LL ans=0;
	std::sort(a+1,a+n+1,cmp);
	for(re int i=1;i<=n;i++) if(!ins(a[i])) ans+=a[i];
	printf("%lld\n",ans);
	return 0;
}

posted @ 2019-02-16 19:35  asuldb  阅读(126)  评论(0编辑  收藏  举报