結果
問題 |
No.3112 Decrement or Mod Game
|
ユーザー |
![]() |
提出日時 | 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 |
ソースコード
#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; }