結果
問題 |
No.68 よくある棒を切る問題 (2)
|
ユーザー |
![]() |
提出日時 | 2025-05-14 13:07:35 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
TLE
|
実行時間 | - |
コード長 | 5,813 bytes |
コンパイル時間 | 960 ms |
コンパイル使用メモリ | 99,956 KB |
実行使用メモリ | 11,940 KB |
最終ジャッジ日時 | 2025-05-14 13:09:36 |
合計ジャッジ時間 | 13,664 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | TLE * 1 -- * 9 |
ソースコード
#include <iostream> #include <vector> #include <cmath> #include <numeric> #include <algorithm> #include <iomanip> // Use long double for calculations involving the length X to ensure high precision. using Real = long double; /** * @brief Check function to determine if it's possible to obtain at least K pieces of length X. * * Given N sticks with lengths L_i, determines if we can cut them to obtain at least K pieces, * each of length exactly X. This is possible if the sum of floor(L_i / X) over all sticks is >= K. * * @param X The target length of the pieces. Must be positive. * @param K The required minimum number of pieces. Must be >= 1. * @param N The total number of initial sticks. * @param L A const reference to the vector containing the lengths of the N sticks. * @return true If it's possible to obtain at least K pieces of length X. * @return false Otherwise. */ bool can(Real X, long long K, int N, const std::vector<long long>& L) { // If X is effectively zero or negative, handle appropriately. // Since K >= 1, we need a positive length X. // A very small positive X allows cutting potentially infinite pieces from any stick of positive length. // Using 1e-18 as a threshold for "practically zero". Choose a value smaller than required precision. if (X <= 1e-18) { // If K>=1, we can always achieve it with tiny X as long as there is at least one stick with L_i > 0. // Since problem constraints state L_i >= 1, this is always true. return true; } long long current_pieces = 0; // Accumulator for the total number of pieces obtained. // Iterate through all sticks for (int i = 0; i < N; ++i) { // Calculate the number of pieces of length X obtainable from the current stick L[i]. // Use long double for the division to maintain precision. // floor function correctly handles cases: returns 0 if L[i] < X. Real pieces_ld = floor((Real)L[i] / X); // Optimization: Check if this single stick provides enough pieces. // K can be up to 5e5. pieces_ld could potentially be very large if X is tiny. // If pieces_ld >= K, we have already met the requirement. if (pieces_ld >= K) { current_pieces = K; // Set current_pieces to K to indicate success (or more than K) break; // Exit loop early as we have enough pieces } // Since pieces_ld < K, it's guaranteed to be less than 5e5. // This value safely fits within a long long. Cast it. long long pieces_ll = (long long)pieces_ld; // Add the pieces obtained from this stick to the total count. // To prevent potential overflow (though unlikely with K <= 5e5), // check if adding pieces_ll would reach or exceed the remaining needed pieces (K - current_pieces). if (K - current_pieces <= pieces_ll) { current_pieces = K; // Cap total pieces at K, indicates success break; // Exit loop early } // Otherwise, add the pieces and continue to the next stick. current_pieces += pieces_ll; } // After checking all sticks (or breaking early), return true if we gathered at least K pieces. return current_pieces >= K; } int main() { // Use fast I/O operations std::ios_base::sync_with_stdio(false); std::cin.tie(NULL); int N; // Number of sticks std::cin >> N; std::vector<long long> L(N); // Vector to store stick lengths long long max_L = 0; // Keep track of the maximum stick length // Read stick lengths and find the maximum length for (int i = 0; i < N; ++i) { std::cin >> L[i]; if (L[i] > max_L) { max_L = L[i]; } } int Q; // Number of queries std::cin >> Q; // Set output precision to satisfy the problem requirement (e.g., 1e-9 error tolerance) // 17 decimal places is usually sufficient for typical competitive programming tasks needing high precision. std::cout << std::fixed << std::setprecision(17); // Process each query for (int i = 0; i < Q; ++i) { long long K_query; // Required number of pieces for this query std::cin >> K_query; // Set up binary search range for the maximum possible length X. // The length X can range from 0 up to the maximum stick length. // We use [0, max_L + 1.0] as the search interval. max_L + 1.0 ensures that max_L is potentially included. Real low = 0.0, high = max_L + 1.0; // Perform binary search for a fixed number of iterations. // 100 iterations reduce the search interval size by a factor of 2^100, // which provides extremely high precision, well beyond typical requirements like 1e-9. for (int iter = 0; iter < 100; ++iter) { // Calculate midpoint safely to avoid potential overflow if low and high were large Real mid = low + (high - low) / 2.0; // Check if it's possible to obtain K_query pieces of length `mid` if (can(mid, K_query, N, L)) { // If yes, `mid` is a possible length. The maximum possible length could be `mid` or even larger. // So, we update the lower bound of our search range to `mid`. low = mid; } else { // If no, `mid` is too long. The maximum possible length must be smaller than `mid`. // So, we update the upper bound of our search range to `mid`. high = mid; } } // After 100 iterations, `low` converges to the maximum possible length X that satisfies the condition. std::cout << low << "\n"; } return 0; }