結果

問題 No.3112 Decrement or Mod Game
ユーザー aaaaaaaaaaa
提出日時 2025-04-19 11:21:58
言語 C++17
(gcc 13.3.0 + boost 1.87.0)
結果
MLE  
実行時間 -
コード長 6,807 bytes
コンパイル時間 974 ms
コンパイル使用メモリ 84,912 KB
実行使用メモリ 814,592 KB
最終ジャッジ日時 2025-04-19 11:22:02
合計ジャッジ時間 4,521 ms
ジャッジサーバーID
(参考情報)
judge2 / judge1
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample -- * 3
other MLE * 1 -- * 64
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <utility>
#include <algorithm>

using namespace std;

// Memoization table: map key is pair<a, b>, value is pair<Alice_wins, Bob_wins> from state (a, b).
// Note: The state (a, b) is canonicalized such that a >= b inside the recursive function where it's the turn of the player with the larger number's turn's equivalent.
// However, the recursive calls themselves might not maintain this order, so memoization key should be pair<a,b> directly.
map<pair<long long, long long>, pair<bool, bool>> memo;

// Function to check if the player whose turn it is wins from state (a, b)
// is_alice_turn: true if it's Alice's turn, false if it's Bob's turn
// Returns true if the current player wins, false otherwise.
bool can_win(long long a, long long b, bool is_alice_turn) {
    // Base cases: If a number is 0, the player whose number is 0 has lost.
    // The player whose turn it is cannot make a move if their number is 0 (game already ended).
    // So, if it's Alice's turn and a is 0, she lost on a previous turn.
    // If it's Bob's turn and b is 0, he lost on a previous turn.
    // Conversely, if it's Alice's turn and b is 0, Bob lost on a previous turn, so Alice wins.
    // If it's Bob's turn and a is 0, Alice lost on a previous turn, so Bob wins.

    if (a == 0) {
        return !is_alice_turn; // If a=0, Alice lost. If it was Alice's turn, she loses. If it was Bob's turn, Bob wins.
    }
    if (b == 0) {
        return is_alice_turn; // If b=0, Bob lost. If it was Alice's turn, she wins. If it was Bob's turn, he loses.
    }

    // Canonicalize state for memoization: always store (max, min)
    pair<long long, long long> state = {a, b};
    if (a < b) swap(state.first, state.second);

    // Check memoization table
    if (memo.count(state)) {
        if (a >= b) { // Original state was a >= b
             if (is_alice_turn) return memo[state].first;
             else return memo[state].second;
        } else { // Original state was a < b
             if (is_alice_turn) return memo[state].second; // If Alice had smaller number (b), result corresponds to Bob having larger number (state.first) in canonical state.
             else return memo[state].first; // If Bob had smaller number (a), result corresponds to Alice having larger number (state.first) in canonical state.
        }
    }

    bool current_player_wins;

    if (is_alice_turn) {
        // Alice's turn (a, b)
        // Alice wins if any of her moves lead to a state where Bob loses.

        // Move 1: Decrease a
        // If a-1 becomes 0, Alice wins immediately.
        // Otherwise, check if Bob loses from (a-1, b).
        if (a > 0 && (a - 1 == 0 || !can_win(a - 1, b, !is_alice_turn))) {
            current_player_wins = true;
        } else {
            // Move 2: Modulo a % b (if a >= b)
            if (a >= b) {
                // If a % b becomes 0, Alice wins immediately.
                // Otherwise, check if Bob loses from (a % b, b).
                if (a % b == 0 || !can_win(a % b, b, !is_alice_turn)) {
                    current_player_wins = true;
                } else {
                     // Neither immediate win nor modulo move leads to Bob losing.
                     // Consider special decrease move patterns based on a/b quotient.
                     long long q = a / b;
                     if (q == 1) { // b <= a < 2b. Alice can reach (b, b) by decreasing.
                         // If Bob loses from (b, b), Alice wins.
                         current_player_wins = !can_win(b, b, !is_alice_turn);
                     } else { // a >= 2b. Alice can "fast-forward" decreases.
                         // If Bob loses from (a%b + b, b), Alice wins.
                         current_player_wins = !can_win(a % b + b, b, !is_alice_turn);
                     }
                }
            } else {
                 // a < b, modulo not possible. Alice can only decrease.
                 // Check if Bob loses from (a-1, b). This was already covered by the first 'if' block.
                 // If we reached here, it means decreasing to a-1 did not lead to immediate win or Bob losing.
                 current_player_wins = false; // No winning move found
            }
        }

    } else {
        // Bob's turn (a, b)
        // Bob wins if any of his moves lead to a state where Alice loses.

        // Move 1: Decrease b
        // If b-1 becomes 0, Bob wins immediately.
        // Otherwise, check if Alice loses from (a, b-1).
         if (b > 0 && (b - 1 == 0 || !can_win(a, b - 1, !is_alice_turn))) {
            current_player_wins = true;
        } else {
            // Move 2: Modulo b % a (if b >= a)
            if (b >= a) {
                 // If b % a becomes 0, Bob wins immediately.
                // Otherwise, check if Alice loses from (a, b % a).
                if (b % a == 0 || !can_win(a, b % a, !is_alice_turn)) {
                    current_player_wins = true;
                } else {
                    // Neither immediate win nor modulo move leads to Alice losing.
                    // Consider special decrease move patterns based on b/a quotient.
                    long long q = b / a;
                     if (q == 1) { // a <= b < 2a. Bob can reach (a, a) by decreasing.
                         // If Alice loses from (a, a), Bob wins.
                        current_player_wins = !can_win(a, a, !is_alice_turn);
                    } else { // b >= 2a. Bob can "fast-forward" decreases.
                        // If Alice loses from (a, b%a + a), Bob wins.
                        current_player_wins = !can_win(a, b % a + a, !is_alice_turn);
                    }
                }
            } else {
                // b < a, modulo not possible. Bob can only decrease.
                // Check if Alice loses from (a, b-1). This was already covered by the first 'if' block.
                // If we reached here, it means decreasing to b-1 did not lead to immediate win or Alice losing.
                current_player_wins = false; // No winning move found
            }
        }
    }

    // Store and return result
    if (a >= b) {
        if (is_alice_turn) memo[state].first = current_player_wins;
        else memo[state].second = current_player_wins;
    } else { // a < b
        if (is_alice_turn) memo[state].second = current_player_wins;
        else memo[state].first = current_player_wins;
    }
    
    return current_player_wins;
}


int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    long long A, B;
    cin >> A >> B;

    // Alice goes first
    if (can_win(A, B, true)) {
        cout << "Alice" << endl;
    } else {
        cout << "Bob" << endl;
    }

    return 0;
}
0