[AcWing 891] Nim游戏
作者:互联网
点击查看代码
#include<iostream>
using namespace std;
int main()
{
int n;
cin >> n;
int res = 0;
while (n --) {
int x;
scanf("%d", &x);
res ^= x;
}
if (res) puts("Yes");
else puts("No");
return 0;
}
- 先手必胜状态和先手必败状态
① 先手必胜状态:可以走到某一个必败状态;
② 先手必败状态:走不到任何一个必败状态; - 结论:假设 $ n $ 堆石子,石子的数目分别是 $ a_1,a_2,\cdots,a_n $ ,如果 $ a_1 \oplus a_2 \oplus \cdots \oplus a_n \neq 0 $ ,则先手必胜,否则,先手必败
① $ 0 \oplus 0 \oplus \cdots \oplus 0 = 0 $ ,说明没有石子可拿;
② 如果 $ a_1 \oplus a_2 \oplus \cdots \oplus a_n = x \neq 0 $ ,那么玩家必然可以通过拿走某一堆里面的若干个石子,使得异或值变为 $ 0 $
证明:不妨设 $ x $ 的二进制表示中,最高位 $ 1 $ 在 $ x $ 的第 $ k $ 位,那么必然存在一个 $ a_i $ ,$ a_i $ 的第 $ k $ 位为 $ 1 $ (反证法:如果 \(a_1,a_2,\cdots,a_n\) 的第 \(k\) 位都为 \(0\),则 \(x\) 的第 \(k\) 位也必然为 \(0\),与最高位 $ 1 $ 在 $ x $ 的第 $ k $ 位矛盾),$ a_i \oplus x < a_i $,那么从第 \(i\) 堆石子中拿走 $ (a_i - a_i \oplus x) $ 个石子,第 \(i\) 堆石子还剩 $a_i - (a_i - a_i \oplus x) = a_i \oplus x $ ,此时 $ a_1 \oplus a_2 \oplus \cdots \oplus a_n = x \oplus x = 0 $
③ 如果 $ a_1 \oplus a_2 \oplus \cdots \oplus a_n = 0 $,那么无论玩家怎么拿,最终的异或值都不为 $ 0 $
反证法:假设玩家从第 \(i\) 堆石子拿走若干个,异或值为 $ 0 $,不妨设第 $ i $ 堆还剩下 $ a_i^{'} $ 个,$ 0 \leqslant a_i^{'} < a_i $ ,$ a_1 \oplus a_2 \oplus \cdots a_i^{'} \oplus \cdots \oplus a_n = 0 $,那么 $ (a_1 \oplus a_2 \oplus \cdots \oplus a_i \oplus \cdots \oplus a_n) \oplus (a_1 \oplus a_2 \oplus \cdots \oplus a_i^{'} \oplus \cdots \oplus a_n) = 0 \oplus (a_i \oplus a_i^{'}) = 0 $,推出 $ a_{i} \oplus a_{i}^{'} = 0 \rightarrow a_{i} = a_i^{'} $,与 $ a_i^{'} < a_i $ 矛盾,证明完毕
④ 基于上述结论,当先手遇到的是 $ a_1 \oplus a_2 \oplus \cdots \oplus a_n = x \neq 0 $,必然可以通过拿走某一堆里面的若干个石子,使得异或值变为 $ 0 $,而后手无论怎么拿,最终的异或值都不为 $ 0 $,不断重复这个过程,后手必然会遇到 $ 0 \oplus 0 \oplus \cdots \oplus 0 = 0 $ 这一失败的局面,而当先手遇到的是 $ a_1 \oplus a_2 \oplus \cdots \oplus a_n = 0 $ 的局面时,都会给后手创造 $ a_1 \oplus a_2 \oplus \cdots \oplus a_n = x \neq 0 $ 的局面,先手必败
标签:891,Nim,必败,石子,异或,cdots,oplus,neq,AcWing 来源: https://www.cnblogs.com/wKingYu/p/16273836.html