题解 | Enjoy the game
对于当前玩家,我们记:
- r – 牌堆中剩余的牌数,
- l – 对手上一次所取的牌数(即当前玩家最多只能取 l 张牌)。
当前状态为 (r , l)。
一次合法的走法是选择一个数 x,满足
1 ≤ x ≤ l (至少取一张,至多取 l 张) x ≤ r (取牌数不能超过剩余牌数)
并将状态变为(r – x , x) (取走的牌成为新的上界)
取走最后一张牌的玩家获胜。因此,当 r ≤ l 时,当前行动的玩家可以取走剩余的牌并立即获胜。整个游戏的结果由如下位置集合决定:P = { (r , l) | r > l 且对当前玩家而言为必败位置 }
1. 必败位置的特征
对于正整数 a,定义
lowbit(a) = a 的二进制表示中最低位的 1 的值
= 能整除 a 的最大的 2 的幂
= a & -a
断言(r , l) 是必败态 ⇔ l < lowbit(r)
通过对 r 进行归纳证明
基础情况r = 1。此时 lowbit(1)=1。
由于 l ≥ 1,条件 l < lowbit(r) 永不成立,
而 (1 , l) 对当前行动的玩家是必胜的(他可以取走最后一张牌)。
因此该断言在 r = 1 时成立。
归纳步骤——假设该断言对所有小于 r 的数均已成立。
情况 1 – l < lowbit(r)
由于 lowbit(r) 是 r 的最小 1 比特位,因此 r 可写为r = lowbit(r) · t (t 为奇数, t ≥ 1)
l 小于 lowbit(r),因此每一个合法的走法 x (1 ≤ x ≤ l) 都满足
x < lowbit(r) ⇒ x 也是 lowbit(r) 的约数 r – x = lowbit(r)·t – x 仍然 ≥ lowbit(r) lowbit(r – x) = lowbit(r)
因此,在走法 x 之后,新的上界 x 仍然小于lowbit(r – x)。根据归纳假设,得到的位置(r – x , x)
对于下一个玩家是必败的。每一个合法的走法都会使对手进入必败位置 ——因此 (r , l) 本身也是必败的。
情况2 – l ≥ lowbit(r)
选择 x = lowbit(r)。
x 是合法的,因为
x = lowbit(r) ≤ l (由假设条件)
x < r (因为 r 不是 2 的幂,除非 r 恰好等于 lowbit(r);
此时 r‑x = 0,游戏结束)
移动后我们到达(r – lowbit(r) , lowbit(r))
现在新的堆的大小为 r' = r – lowbit(r)。r 与 r' 的唯一二进制位差异在于原本最低的置位(值为 lowbit(r))消失了。结果,lowbit(r')严格大于lowbit(r)。因此新的上界(即 lowbit(r))小于 lowbit(r'),所以根据归纳假设,所得位置对于即将移动的对手是一个必败位置。
因此,当前玩家存在一个必胜的移动,故 (r , l) 是一个必胜位置。
这完成了归纳证明。∎
2. 初始局面
初始局面是r = n , l = n‑1
l = n‑1 总是 ≥ lowbit(n),除非n 是 2 的幂。事实上,当 n = 2^k 时,lowbit(n) = n > n‑1 = l ,对于当前玩家,我们记:
r – 牌堆中剩余的牌数,
l – 对手上一次所取的牌数(即当前玩家最多只能取 l 张牌)。
当前状态为 (r , l)。
一次合法的走法是选择一个数 x,满足
1 ≤ x ≤ l (至少取一张,至多取 l 张)
x ≤ r (取牌数不能超过剩余牌数)
并将状态变为
(r – x , x) (取走的牌成为新的上界)
取走最后一张牌的玩家获胜。
因此,当 r ≤ l 时,当前行动的玩家可以取走剩余的牌并立即获胜。
整个游戏的结果由如下位置集合决定:
P = { (r , l) | r > l 且对当前玩家而言为必败位置 }
1. 必败位置的特征
对于正整数 a,定义
lowbit(a) = a 的二进制表示中最低位的 1 的值
= 能整除 a 的最大的 2 的幂
= a & -a
断言
(r , l) 是必败态 ⇔ l < lowbit(r)
通过对 r 进行归纳证明
基础情况 r = 1。此时 lowbit(1)=1。
由于 l ≥ 1,条件 l < lowbit(r) 永不成立,
而 (1 , l) 对当前行动的玩家是必胜的(他可以取走最后一张牌)。
因此该断言在 r = 1 时成立。
归纳步骤——假设该断言对所有小于 r 的数均已成立。
情况 1 – l < lowbit(r)
由于 lowbit(r) 是 r 的最小 1 比特位,因此 r 可写为
r = lowbit(r) · t (t 为奇数, t ≥ 1)
l 小于 lowbit(r),因此每一个合法的走法 x (1 ≤ x ≤ l) 都满足
x < lowbit(r) ⇒ x 也是 lowbit(r) 的约数
r – x = lowbit(r)·t – x 仍然 ≥ lowbit(r)
lowbit(r – x) = lowbit(r)
因此,在走法 x 之后,新的上界 x 仍然小于
lowbit(r – x)。根据归纳假设,得到的位置
(r – x , x)
对于下一个玩家是必败的。
每一个合法的走法都会使对手进入必败位置 ——
因此 (r , l) 本身也是必败的。
情况2 – l ≥ lowbit(r)
选择 x = lowbit(r)。
x 是合法的,因为
x = lowbit(r) ≤ l (由假设条件)
x < r (因为 r 不是 2 的幂,除非 r 恰好等于 lowbit(r);
此时 r‑x = 0,游戏结束)
移动后我们到达
(r – lowbit(r) , lowbit(r))
现在新的堆的大小为 r' = r – lowbit(r)。
r 与 r' 的唯一二进制位差异在于原本最低的置位(值为 lowbit(r))消失了。
结果,lowbit(r') 严格大于 lowbit(r)。
移动后,局面变为 (r', bound') = (r - lowbit(r), lowbit(r))。此时,新的上界是 bound' = lowbit(r),而新堆大小的低位是 lowbit(r')。由于 lowbit(r) < lowbit(r'),根据归纳假设,对手处于必败态。
因此,当前玩家存在一个必胜的移动,故 (r , l) 是一个必胜位置。
这完成了归纳证明。∎
2. 初始局面
初始局面是
r = n , l = n‑1
l = n‑1 总是 ≥ lowbit(n),除非 n 是 2 的幂。
事实上,当 n = 2^k 时,
lowbit(n) = n > n‑1 = l ,
因此该局面属于必败集合 P。
如果 n 不是 2 的幂,则 lowbit(n) ≤ n/2 ≤ n‑1 = l,
因此先手玩家可以取走 x = lowbit(n) 张牌。
根据上述论证,结果位置 (n‑lowbit(n), lowbit(n)) 对于对手来说是一个必败位置,也就是说先手玩家有必胜策略。
3. 决策规则
如果 n 是 2 的幂 → 先手输 → 输出 Alice
否则 → 先手赢 → 输出 Bob
由于输入范围可达 10^18,lowbit(n) 可通过 n & -n(64 位整数)计算得到。
测试“2 的幂”只需判断 n & (n-1) == 0 即可。
因此该局面属于必败集合 P。
如果 n 不是 2 的幂,则 lowbit(n) ≤ n/2 ≤ n‑1 = l,因此先手玩家可以取走 x = lowbit(n) 张牌。根据上述论证,结果位置 (n‑lowbit(n), lowbit(n)) 对于对手来说是一个必败位置,也就是说先手玩家有必胜策略。
3. 决策规则
- 如果 n 是 2 的幂 → 先手输 → 输出 Alice
- 否则 → 先手赢 → 输出 Bob
由于输入范围可达 10^18,lowbit(n) 可通过 n & -n(64 位整数)计算得到。测试“2 的幂”只需判断 n & (n-1) == 0 即可。
#include <bits/stdc++.h>
using namespace std;
using ll = unsigned long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
ll n;
cin >> n;
if ((n & (n - 1)) == 0)
cout << "Alice" << endl;
else
cout << "Bob" << endl;
}
各类牛客算法编程训练联赛、集训营
