810. 黑板异或游戏
数学时刻提醒我们:保持谦逊!
我的思路
- 想了半天,完全没思路。但是我知道,这题一定代码简单,因为一定存在先手必胜的条件。
博弈的整体思路
- 经验:奇偶性
- 推导先手必胜条件,或者后手必败条件。
数学之美
Reference :
Alice 和 Bob 都是聪明的人。
下面,分析 Alice 必胜的条件。
-
当初始数组 n u m s nums nums 中的所有数字的异或和为 0 时,Alice 必胜。即:
n u m s [ 0 ] ⊕ n u m s [ 1 ] ⊕ … ⊕ n u m s [ n − 2 ] ⊕ n u m s [ n − 1 ] = 0 nums[0] \oplus nums[1] \oplus \ldots \oplus nums[n-2] \oplus nums[n-1]= 0 nums[0]⊕nums[1]⊕…⊕nums[n−2]⊕nums[n−1]=0 不妨记 n u m s [ 0 ] ⊕ n u m s [ 1 ] ⊕ … ⊕ n u m s [ n − 2 ] ⊕ n u m s [ n − 1 ] nums[0] \oplus nums[1] \oplus \ldots \oplus nums[n-2] \oplus nums[n-1] nums[0]⊕nums[1]⊕…⊕nums[n−2]⊕nums[n−1] 为 S S S. -
当 S ≠ 0 S \ne 0 S=0 时,Alice 必胜的条件是:Alice 先去掉一个数字(记为 n u m s [ k 0 ] nums[k_0] nums[k0]),此时的数组异或和记为 S ′ S' S′,然后 Bob 去除任意一个数字( n u m s [ k ] nums[k] nums[k])后,记此时数组异或和为 S ′ ′ S'' S′′,必然有 S ′ ′ = 0 S''=0 S′′=0.
- Bob是个聪明的人,如果 Bob 发现去除某一个数字可以让 S ′ ′ ≠ 0 S''\ne0 S′′=0,那么他一定会去除这个数字,因为他不想输。
- 因此,Bob去除的数字必须是任意的,然后 Bob 必输,Alice 才能必胜。
- 根据上述分析,有: S = n u m s [ 0 ] ⊕ n u m s [ 1 ] ⊕ … ⊕ n u m s [ n − 2 ] ⊕ n u m s [ n − 1 ] S ′ = n u m s [ 0 ] ⊕ … ⊕ n u m s [ k 0 − 1 ] ⊕ n u m s [ k 0 + 1 ] … ⊕ n u m s [ n − 1 ] S ′ ′ = n u m s [ 0 ] ⊕ … ⊕ n u m s [ k 0 − 1 ] ⊕ n u m s [ k 0 + 1 ] ⊕ … ⊕ n u m s [ k − 1 ] ⊕ n u m s [ k + 1 ] … ⊕ n u m s [ n − 1 ] S=nums[0] \oplus nums[1] \oplus \ldots \oplus nums[n-2] \oplus nums[n-1]\\S'=nums[0] \oplus \ldots \oplus nums[k_0-1]\oplus nums[k_0+1] \ldots\oplus nums[n-1]\\ S''=nums[0] \oplus \ldots \oplus nums[k_0-1]\oplus nums[k_0+1] \oplus\ldots\\ \oplus nums[k-1]\oplus nums[k+1] \ldots \oplus nums[n-1] S=nums[0]⊕nums[1]⊕…⊕nums[n−2]⊕nums[n−1]S′=nums[0]⊕…⊕nums[k0−1]⊕nums[k0+1]…⊕nums[n−1]S′′=nums[0]⊕…⊕nums[k0−1]⊕nums[k0+1]⊕…⊕nums[k−1]⊕nums[k+1]…⊕nums[n−1] S = S ′ ⊕ n u m s [ k 0 ] S ′ = S ′ ′ ⊕ n u m s [ k ] S=S'\oplus nums[k_0]\\S'=S''\oplus nums[k] S=S′⊕nums[k0]S′=S′′⊕nums[k]即, S ′ ′ = S ′ ⊕ n u m s [ k ] 0 ≤ k ≤ n − 1 , k ≠ k 0 S''=S'\oplus nums[k] \\ 0 \le k \le n-1, k\ne k_0 S′′=S′⊕nums[k]0≤k≤n−1,k=k0
- 也就是说,因为
k
k
k 的任意性,Alice 必胜时,
S
′
′
=
0
S''=0
S′′=0 恒成立,有:
S ′ ⊕ n u m s [ 0 ] = 0 … S ′ ⊕ n u m s [ k 0 − 1 ] = 0 S ′ ⊕ n u m s [ k 0 + 1 ] = 0 … S ′ ⊕ n u m s [ n − 1 ] = 0 S'\oplus nums[0] = 0\\\ldots\\S'\oplus nums[k_0-1]=0\\S'\oplus nums[k_0+1]=0\\ \ldots \\S'\oplus nums[n-1]=0 S′⊕nums[0]=0…S′⊕nums[k0−1]=0S′⊕nums[k0+1]=0…S′⊕nums[n−1]=0- 上述共 n − 1 n-1 n−1 个式子( n n n 是 n u m s nums nums 的长度)。
- 将上述 n − 1 n-1 n−1 个式子异或: ( S ′ ⊕ n u m s [ 0 ] ) ⊕ … ⊕ ( S ′ ⊕ n u m s [ k 0 − 1 ] ) ⊕ ( S ′ ⊕ n u m s [ k 0 + 1 ] ) ⊕ … ⊕ ( S ′ ⊕ n u m s [ n − 1 ] ) = 0 (S'\oplus nums[0]) \oplus \ldots \oplus(S'\oplus nums[k_0-1])\oplus\\(S'\oplus nums[k_0+1])\oplus \ldots \oplus(S'\oplus nums[n-1])=0 (S′⊕nums[0])⊕…⊕(S′⊕nums[k0−1])⊕(S′⊕nums[k0+1])⊕…⊕(S′⊕nums[n−1])=0
- 整理得:
(
S
′
⊕
…
⊕
S
′
)
⊕
(
n
u
m
s
[
0
]
⊕
…
⊕
n
u
m
s
[
k
0
−
1
]
⊕
n
u
m
s
[
k
0
+
1
]
…
⊕
n
u
m
s
[
n
−
1
]
)
=
0
(S'\oplus\ldots\oplus S')\oplus \\(nums[0] \oplus \ldots \oplus nums[k_0-1]\oplus nums[k_0+1] \ldots\oplus nums[n-1]) = 0
(S′⊕…⊕S′)⊕(nums[0]⊕…⊕nums[k0−1]⊕nums[k0+1]…⊕nums[n−1])=0
即, ( S ′ ⊕ … ⊕ S ′ ) ⏟ n − 1 个 ⊕ ( S ′ ) = 0 \underbrace{(S'\oplus\ldots\oplus S')}_{n-1个} \oplus (S')=0 n−1个 (S′⊕…⊕S′)⊕(S′)=0
即, ( S ′ ⊕ … ⊕ S ′ ) ⏟ n 个 = 0 \underbrace{(S'\oplus\ldots\oplus S')}_{n个}=0 n个 (S′⊕…⊕S′)=0 - S ′ ′ = 0 S''=0 S′′=0 恒成立的条件是 n 个 S ′ ′ S'' S′′异或的结果为 0 ,显然,当 n n n 是偶数时,恒成立,即, n n n 是偶数时,Alice 必胜。
综上,Alice 必胜的条件(满足其中之一即可)是:
- S = 0 S = 0 S=0
- n n n 是偶数
根据上述分析可以写出AC代码:
class Solution {
public:
bool xorGame(vector<int>& nums) {
int n = nums.size();
if (!(n & 1)){
return true;
}
int S = 0;
for (auto item : nums){
S ^= item;
}
return S == 0;
}
};
复杂度分析:
- 时间复杂度: O ( n ) O(n) O(n),一层for。
- 空间复杂度: O ( 1 ) O(1) O(1),使用了可数个变量。
2021.05.22 21:16
今天,中华拓荒人——袁隆平逝世了。
稻浆小满先生汗,谷库丰隆国士心。
诸君勿忘贫苦日,吾辈永志挖水人!