結果
| 問題 |
No.1816 MUL-DIV Game
|
| コンテスト | |
| ユーザー |
qwewe
|
| 提出日時 | 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;
}
qwewe