bzoj1299: [LLH邀请赛]巧克力棒

传送门

博,博弈论?
大概可以理解成从一个盒子里取出几堆石子,或者对已经取出的盒子做nim博弈,问先手是否必胜
说实话直接dfs就能过
考虑一下,取出石子意味着改变当前的异或和,只有当取出的石子的异或和为\(0\)的时候,才能改变当前的先后手输赢状况
刚开始石子数为\(0\),先手必败,那么它必须得取出一个异或和为\(0\)的石子集合,且剩下的石子中不存在异或和为\(0\)的集合。不难发现如果剩下部分还存在异或和为\(0\)的集合的话,取出来也没有问题
所以就变成判断是否存在一个集合异或和为\(0\)了,线性基即可

//minamoto
#include<bits/stdc++.h>
#define R register int
#define fp(i,a,b) for(R i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R i=a,I=b-1;i>I;--i)
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
    R res,f=1;char ch;
    while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
    for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
    return res*f;
}
const int N=15;
int p[35],a[N],n;
bool ins(R x){
	fd(i,30,0)if(x&(1<<i)){
		if(!p[i])return p[i]=x,true;
		x^=p[i];
	}return false;
}
inline void clr(){memset(p,0,sizeof(p));}
void solve(){
	n=read(),clr();fp(i,1,n)a[i]=read();
	fp(i,1,n)if(!ins(a[i]))return (void)(puts("NO"));
	puts("YES");
}
int main(){
	int T=10;
	while(T--)solve();
	return 0;
}
posted @ 2018-12-02 21:49  bztMinamoto  阅读(210)  评论(0编辑  收藏  举报
Live2D