結果
問題 |
No.3112 Decrement or Mod Game
|
ユーザー |
![]() |
提出日時 | 2025-04-19 01:02:57 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
MLE
|
実行時間 | - |
コード長 | 4,568 bytes |
コンパイル時間 | 1,038 ms |
コンパイル使用メモリ | 83,780 KB |
実行使用メモリ | 814,592 KB |
最終ジャッジ日時 | 2025-04-19 01:03:01 |
合計ジャッジ時間 | 3,512 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | -- * 3 |
other | AC * 2 MLE * 1 -- * 62 |
ソースコード
#include <iostream> // 用于标准输入输出流 #include <vector> // 虽然未使用,但通常包含在C++标准库中 #include <numeric> // 虽然未使用,但包含一些数值算法 #include <map> // 用于存储记忆化结果 #include <utility> // 用于 std::pair #include <algorithm> // 用于 std::swap (虽然未使用,但可能需要) // 使用 long long 类型处理大整数,最大可达 10^18 using ll = long long; // 使用 map 来存储已经计算过的状态结果,避免重复计算 // 键是 (a, b) 状态对,值是布尔类型表示当前玩家是否能赢 std::map<std::pair<ll, ll>, bool> memo; // 函数 can_win(a, b) 判断: // 当前轮到的玩家持有数字 'a',对手持有数字 'b',当前玩家是否能够强制获胜? bool can_win(ll a, ll b) { // 基本情况 1: 如果当前玩家的数字 a 为 0 // 这意味着在上一个对手的回合后,当前玩家的数字变成了0。 // 根据规则“先将自己数字变成0者获胜”,这意味着对手在上一步没有获胜, // 而现在轮到当前玩家时数字已经是0,这似乎有些矛盾。 // 更准确地说,如果一个玩家通过操作使自己的数字变为0,则该玩家立即获胜。 // 递归调用的含义是:如果对手从下一个状态无法获胜,则当前玩家获胜。 // 因此,如果 a=0,表示当前玩家无法进行任何操作使 a 变为 0(因为它已经是0了)。 // 这通常意味着之前的状态转移有问题,或者这是一个不应该达到的初始状态。 // 按照游戏逻辑,轮到你时你的数字是0,你应该已经输了。 if (a == 0) { return false; } // 基本情况 2: 如果对手的数字 b 为 0 // 这意味着对手在他的上一个回合使得 b=0 并获胜了。 // 所以当前玩家 (a, 0) 已经输了。 if (b == 0) { return false; } // 检查记忆化表,如果当前状态 (a, b) 已经计算过,直接返回结果 std::pair<ll, ll> state = {a, b}; if (memo.count(state)) { return memo[state]; } // 优化: 如果 a >= 2b,当前玩家总能获胜。 // 这个结论的证明基于:如果取模操作不能直接导向胜利(即对手在 (b, a % b) 状态下能赢), // 那么可以通过连续的 (a-1, b-1) 转换,最终归结为一个必胜状态。 // (需要 b > 0,这个条件在上面的 b == 0 判断后是满足的) if (a >= 2 * b) { memo[state] = true; // 记录结果 return true; } // 递归计算:当前玩家获胜,当且仅当存在一个操作,使得操作后的状态对于下一个玩家(即当前对手)来说是必败的。 // 必败状态意味着 can_win 返回 false。 // 考虑操作 1: 将自己的数字减 1 (a -> a - 1) // 操作后的状态对对手来说是 (b, a - 1)。 // 当前玩家获胜,如果对手从 (b, a - 1) 状态开始无法获胜。 // 获胜条件: !can_win(b, a - 1) if (!can_win(b, a - 1)) { memo[state] = true; // 记录结果 return true; // 找到一个获胜策略 } // 考虑操作 2: 将自己的数字替换为 a % b (仅当 a >= b 时可行) // 操作后的状态对对手来说是 (b, a % b)。 // 当前玩家获胜,如果对手从 (b, a % b) 状态开始无法获胜。 // 获胜条件: !can_win(b, a % b) if (a >= b) { // 注意:如果 a % b == 0,这个操作直接使当前玩家获胜。 // 递归调用 !can_win(b, 0) 会返回 !false = true,所以这个情况被正确处理了。 if (!can_win(b, a % b)) { memo[state] = true; // 记录结果 return true; // 找到一个获胜策略 } } // 如果以上所有可能的操作都不能保证当前玩家获胜(即所有操作都会导向对手的必胜状态) // 那么当前玩家处于必败状态。 memo[state] = false; // 记录结果 return false; } int main() { // 加速标准输入输出流 std::ios_base::sync_with_stdio(false); std::cin.tie(NULL); ll a, b; // 输入 Alice 和 Bob 的初始数字 std::cin >> a >> b; // Alice 先手,初始状态是 (A, B)。我们需要判断 Alice 是否能赢。 if (can_win(a, b)) { std::cout << "Alice" << std::endl; // 如果 Alice 能赢 } else { std::cout << "Bob" << std::endl; // 如果 Alice 不能赢(即 Bob 赢) } return 0; // 程序正常结束 }