結果
問題 |
No.1816 MUL-DIV Game
|
ユーザー |
![]() |
提出日時 | 2025-05-14 12:58:09 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 44 ms / 2,000 ms |
コード長 | 4,450 bytes |
コンパイル時間 | 561 ms |
コンパイル使用メモリ | 82,688 KB |
実行使用メモリ | 8,320 KB |
最終ジャッジ日時 | 2025-05-14 12:59:24 |
合計ジャッジ時間 | 2,173 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 27 |
ソースコード
#include <iostream> #include <vector> #include <set> #include <algorithm> // Needed for std::prev // Main function int main() { // Faster I/O for competitive programming std::ios_base::sync_with_stdio(false); std::cin.tie(NULL); int N; // Number of integers std::cin >> N; // Use std::multiset to store the numbers on the blackboard. // A multiset keeps elements sorted automatically, which is useful for finding // the smallest and largest elements efficiently. // Use long long type to handle potentially large products, up to 10^18. // The maximum initial value is 10^9, so 10^9 * 10^9 = 10^18 fits within long long. std::multiset<long long> board; for (int i = 0; i < N; ++i) { long long A_i; std::cin >> A_i; board.insert(A_i); } // If N=1, the game ends immediately before any move. // The only number on the board is the answer. if (N == 1) { // Since N >= 1 and A_i >= 1 are guaranteed by constraints, // the board is non-empty. We can safely access the first element. std::cout << *board.begin() << std::endl; return 0; } // Game simulation for N > 1 bool alice_turn = true; // Alice goes first // The game continues until only one number remains. // This requires exactly N-1 moves in total. for (int k = 0; k < N - 1; ++k) { // The loop invariant ensures board.size() >= 2 before each iteration starts. // This is because we start with N >= 2, and each step reduces the size by 1. // The loop runs N-1 times, ending when the size becomes 1. if (alice_turn) { // Alice's move: Maximize the final result. // Her operation is multiplication. Intuitively, multiplying larger numbers leads to larger results. // However, Bob wants to minimize and can remove large numbers. // A strategy analysis suggests Alice might want to protect large numbers. // Multiplying the smallest two numbers seems to be a good strategy for Alice. // It avoids creating extremely large numbers early that Bob can target, // potentially allowing more moderately large numbers to survive. long long x = *board.begin(); // Get the smallest element board.erase(board.begin()); // Remove it from the multiset long long y = *board.begin(); // Get the new smallest element (second smallest originally) board.erase(board.begin()); // Remove it // Calculate the product and insert it back. // Potential overflow is handled by using long long. board.insert(x * y); } else { // Bob's move: Minimize the final result. // His operation is ceiling division: ceil(x/y). // Bob can always choose x and y such that ceil(min(x,y)/max(x,y)) = 1. // For example, pick any two numbers a, b. Let x=min(a,b), y=max(a,b). Then ceil(x/y)=1. // Since Bob wants to minimize the final result, making a 1 is generally his best move. // To make this move most effective, Bob should remove the largest numbers from the board. // This prevents Alice from using them in later multiplications. // Get an iterator to the largest element (which is the last element in std::multiset) auto it_y = std::prev(board.end()); board.erase(it_y); // Remove the largest element // Get an iterator to the new largest element (which was the second largest initially) // Since the board size was >= 2 before this move, after removing one element, // it's guaranteed to have at least one element left. auto it_x = std::prev(board.end()); board.erase(it_x); // Remove this element as well // Insert 1 into the multiset, representing the result of Bob's division. board.insert(1LL); } // Switch turns for the next iteration alice_turn = !alice_turn; } // After N-1 moves, exactly one number remains on the board. // This number is the final answer. Since the board contains exactly one element, // *board.begin() gives that element. std::cout << *board.begin() << std::endl; return 0; }