题解 | 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)rr' 的唯一二进制位差异在于原本最低的置位(值为 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^18lowbit(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;
}

算法编程训练 文章被收录于专栏

各类牛客算法编程训练联赛、集训营

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务