[P4301][CQOI2013]新Nim游戏(线性基)

Nim游戏的结论为,当目前所有数字异或和不为零是先手必胜,必胜策略为使得操作后的异或和为0。

所以如果在这个题目下后手想赢,就要拿完后使异或和为0,所以先手就要使后手无法做到这个操作,也就是说使第一轮拿完后,任意几堆火柴数量的异或和都不为零。用贪心的思想,把数从大到小排序。对于一个数,如果能插入线性基则插入,不能则添加到答案中。对于一个位置,先用大数占上而拿走之后的小数,最后答案就会比较小。

#include
#include
#include
using namespace std;
const int N=110;
namespace io{
	const int SIZE=(1<<21)+1;
	char ibuf[SIZE],*iS,*iT,obuf[SIZE],*oS=obuf,*oT=oS+SIZE-1,c,qu[55];int qr;
	#define gc() (iT==iS?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),iT==iS?EOF:*iS++):*iS++)
	inline void flush(){
		fwrite(obuf,1,oS-obuf,stdout);
		oS=obuf;
	}
	inline void putc(char x){
		*oS++ =x;
		if(oS==oT)flush();
	}
	template 
	inline void gi(I &x){
		for(c=gc();c<'0'||c>'9';c=gc());
		for(x=0;c>='0'&&c<='9';c=gc())x=x*10+(c&15);
	}
	template 
	inline void print(I &x){
		if(!x)putc('0');
		while(x)qu[++qr]=x%10+'0',x/=10;
		while(qr)putc(qu[qr--]);
	}
}
using io::gi;
using io::putc;
using io::print;
int n,a1[N],b1[35];
long long ans=0;
bool cmp(int a,int b){
	return a>b;
}
int main(){
	gi(n);
	for(int i=1;i<=n;++i)gi(a1[i]);
	sort(a1+1,a1+n+1,cmp);
	memset(b1,0,sizeof b1);
	for(int tmp,i=1;i<=n;++i){
		tmp=a1[i];
		for(int j=30;j>=0;--j){
			if(tmp&(1<

 

你可能感兴趣的:(线性基)