1. 题目来源
链接:810. 黑板异或游戏
相关题目:[博弈论] Nim游戏及SG函数(经典+台阶+集合+拆分)
2. 题目解析
数学题,思维题,博弈论。
相较于 Nim
游戏来讲,这个还是比较简单的题目了。
结论比较难猜。博弈论两个关键概念,必胜态、必败态。我们记数组所有元素异或和为 S
,数组长度为 n
。
- 必胜态:
S
为 0,或者n
为偶数。 - 必败态:
S
不为 0,且n
为奇数。
简单数学归纳法即可证明:
- 当
n=0
时,异或和为 0,当前一定必胜,成立。 - 假设当
k<n
时,成立。考虑k=n
时,是否成立。- 当
k
为奇数时,不论怎么取石子,取完一定为偶数,走向必胜态,故当前为必败态。 - 当
k
为偶数时:- 当
S=0
,即根据游戏规则,已经胜利了。 - 当
S!=0
,仅需证明至少存在一种拿法,使得拿完之后局面转为必败态,即总个数为奇数且S!=0
。总个数为奇数显然成立,考虑反证法,设当前S=x1^x2^...^xn
,当前S != 0
,若不存在一种拿法,则对应任意拿法,拿任意一个数后剩余数的异或和均为 0。从S
中拿xi
等价于S^xi=0
,即S=xi
,针对所有x
均成立。则有S=x1=x2=x3=...=xn=0
,则矛盾。故反证不成立,即至少存在一种拿法,使得拿完之后异或值不为 0,且个数必然为奇数,为必败态。
- 当
- 当
时间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度:
O
(
1
)
O(1)
O(1)
代码:
class Solution {
public:
bool xorGame(vector<int>& nums) {
int n = nums.size();
if ((n & 1) == 0) return true; // 注意优先级,== 高于 & ^ |,低于移位运算符
int cur = 0;
for (auto e : nums) cur ^= e;
return cur == 0;
}
};