本文搬运自本人初中博客园博客,若图片加载不出来,可到原文查看:https://www.cnblogs.com/zhangtingxi/p/16004931.html

题目

NN 堆石子,两人轮流从其中一堆取至少一个石子,问先手是否存在必胜策略。

结论

异或不为0,先手必胜。

证明

kk 为某一堆取完后的剩余个数,ii 为被取那堆石子的编号,则取完后的异或和为 x1  xor  x2  xorxor  xi1  xor  xi+1  xorxor  xn  xor  kx_1\;xor\;x_2\;xor\dots xor\;x_{i-1}\;xor\;x_{i+1}\;xor\dots xor\;x_n\;xor\; k

情况一:异或和为0

  1. 总数为0,此时先手输了
  2. 总数不为0,此时先手还要使异或和为0,就必须使得 k=xik=x_i,然而由于至少取一个,所以这是不可能的,所以必然会转为情况二。

情况二:异或和不为0

可以证明,必然可以取为0。

S=x1  xor  x2  xorxor  xnS=x_1\;xor\;x_2\;xor\dots xor\;x_nxix_ixx 中的最大值。

  1. SS 的二进制位数小于 xix_i 的位数,则 xix_i 必然可以凑出一个数使得其异或 SS 等于0。
  2. SS 的二进制位数和 xix_i 的二进制位数相同,需满足 kxik\leqslant x_iS  xor  xi  xor  k=0S\;xor\; x_i\;xor\;k=0。由于 S  xor  xiS\;xor\; x_i 时已经使得二进制最高位为0,所以 kk 的二进制最高位必然为0。kk 在二进制的最高位已经满足小于 xix_i,后面的位数可以随便取,那么只需要取 S  xor  xiS\;xor\; x_i 即可(这个数的二进制最高位也为0)。

代码

1
2
3
4
5
6
7
8
9
10
11
#include<bits/stdc++.h>
using namespace std;
int n, m, i, j, k, T;

int main()
{
scanf("%d", &n);
for(i=1; i<=n; ++i) scanf("%d", &k), m^=k;
printf(m ? "win" : "lose");
return 0;
}