結果
| 問題 | No.68 よくある棒を切る問題 (2) | 
| コンテスト | |
| ユーザー |  qwewe | 
| 提出日時 | 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;
}
            
            
            
        