石子 无限拿
给定 n 堆石子,两位玩家轮流操作,每次操作可以从任意一堆石子中拿走任意数量的石子(可以拿完,但不能不拿),最后无法进行操作的人视为失败。
问如果两人都采用最优策略,先手是否必胜。
思路
若为 2, 3堆, 先手在3堆里拿1个, 为 2 2。
之后只要跟后手拿的数量相同, 后手一定失败。
定理:
a
1
∧
a
2
∧
a
3
.
.
.
∧
a
n
=
0
先手必败
a_{1} \wedge a_{2} \wedge a_{3}...\wedge a_{n}= 0 先手必败
a1∧a2∧a3...∧an=0先手必败
证明:
0
∧
0
∧
0
∧
0...
∧
0
=
0
a
1
∧
a
2
∧
a
3
.
.
.
∧
a
n
≠
0
\begin{align*} 0\wedge0\wedge0\wedge0...\wedge0 = 0\\ a_{1} \wedge a_{2} \wedge a_{3}...\wedge a_{n} \not= 0 \\ & \end{align*}
0∧0∧0∧0...∧0=0a1∧a2∧a3...∧an=0
不等于0时, 设结果为
x
x
x
x
x
x 的二进制表示为
10100100
10100100
10100100
a
i
a_i
ai的二进制表示
1100100110
1100100110
1100100110
一定存在
a
i
a_i
ai 在
x
x
x 最高位
k
k
k 位上为1。
则
a
i
∧
x
<
a
i
a_{i} \wedge x < a_i
ai∧x<ai , 那么就拿走 少的那一部分。
此时
a
i
=
a
i
∧
x
a_{i}= a_{i} \wedge x
ai=ai∧x 带入到原来式子后得到:
x
∧
x
=
0
x \wedge x = 0
x∧x=0
故先手必赢。
等于0时, 设同样可以拿走一些, 剩下
a
i
′
a_i'
ai′个
a
1
∧
a
2
∧
a
3
.
.
.
a
i
∧
.
.
∧
a
n
=
0
a
1
∧
a
2
∧
a
3
.
.
.
a
i
′
∧
.
.
∧
a
n
=
0
式子相异或得
a
i
∧
a
i
′
=
0
a
i
=
a
i
′
\begin{align*} a_{1} \wedge a_{2} \wedge a_{3}. ..a_{i}\wedge..\wedge a_{n} = 0\\ a_{1} \wedge a_{2} \wedge a_{3}. ..a_{i}'\wedge..\wedge a_{n} = 0\\ 式子相异或得 \\ a_{i}\wedge a_{i}' = 0 \\ a_{i} = a_{i}' \end{align*}
a1∧a2∧a3...ai∧..∧an=0a1∧a2∧a3...ai′∧..∧an=0式子相异或得ai∧ai′=0ai=ai′
代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int readInt()
{
int t ;
scanf("%d", &t);
return t;
}
int n;
int main()
{
int x;
cin >> n;
cin >> x;
n -= 1;
while(n--)
x ^= readInt();
if(x) cout << "Yes\n";
else cout << "No\n";
}