結果
問題 |
No.1977 Extracting at Constant Intervals
|
ユーザー |
![]() |
提出日時 | 2025-05-14 13:16:32 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
MLE
|
実行時間 | - |
コード長 | 8,983 bytes |
コンパイル時間 | 1,129 ms |
コンパイル使用メモリ | 92,876 KB |
実行使用メモリ | 817,440 KB |
最終ジャッジ日時 | 2025-05-14 13:17:55 |
合計ジャッジ時間 | 5,313 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | MLE * 2 -- * 29 |
ソースコード
#include <iostream> #include <vector> #include <numeric> #include <algorithm> #include <map> // Using map for cache as N can be large // Function to compute Greatest Common Divisor (GCD) long long gcd(long long a, long long b) { // Ensure non-negative inputs for standard GCD definition // Absolute values are needed if inputs could be negative, but N, L are positive per constraints. // If a=0 or b=0, standard definitions apply: gcd(a, 0) = |a|. // Constraints: N>=1, L>=1. So a, b >= 1. while (b) { a %= b; std::swap(a, b); } return a; } // Structure to hold precomputed data for a starting index modulo N // This data depends only on the remainder of (i-1) modulo N. struct PrecomputedData { std::vector<long long> period_values; // Stores A[p_k] for one period long long period_sum = 0; // Sum of values in one period std::vector<long long> prefix_sums; // Prefix sums within a period bool computed = false; // Flag to check if data has been computed for this residue class }; int main() { // Fast I/O operations std::ios_base::sync_with_stdio(false); std::cin.tie(NULL); long long N; // Number of elements in A long long M; // Number of times A is concatenated long long L; // Interval length std::cin >> N >> M >> L; std::vector<long long> A(N); // Input array A for (int i = 0; i < N; ++i) { std::cin >> A[i]; } // Calculate the total length of sequence B. N*M can be up to 10^5 * 10^9 = 10^14. Fits in long long. long long total_len = N * M; // Precompute GCD of N and L. Constraints ensure N >= 1, L >= 1. long long common_divisor = gcd(N, L); // Calculate the length of the period P. P = N / gcd(N, L). // Since N >= 1 and common_divisor >= 1, P >= 1. long long P = N / common_divisor; // Cache to store precomputed data for each residue class modulo N. // Using map keyed by residue r_idx = (i-1) % N. Size is at most N. std::map<long long, PrecomputedData> cache; // Initialize max_C to a sufficiently small value. The minimum possible sum could be total_len * min(A_i). // min(A_i) >= -10^4. total_len <= 10^14. Min sum >= -10^18. // Use -4e18 as a safe lower bound. long long max_C = -4e18; bool first_val_set = false; // Flag to track if max_C has been properly initialized // Determine the range of indices `i` to check. // A full check requires iterating i from 1 to L. This is too slow if L is large. // It is known that for functions like g(k) = floor(k/P)*S + Pref(k mod P), the maximum over an interval [k_min, k_max] // is often found near the boundaries of the interval, specifically within P elements from k_min and k_max. // Correspondingly for C_i = g(K_i+1), K_i decreases as i increases. // The maximum C_i is likely found for i near 1 (giving large K_i) or i near L (giving small K_i). // This suggests checking i values in [1, N] and [L-N+1, L] might be sufficient. This is a heuristic. // Let's use this heuristic as it's common in competitive programming problems with similar structure. std::vector<long long> indices_to_check; if (L <= 2 * N) { // If L is small (e.g., comparable to N), check all indices from 1 to L. for (long long i = 1; i <= L; ++i) { indices_to_check.push_back(i); } } else { // If L is large, check the first N indices and the last N indices. for (long long i = 1; i <= N; ++i) { indices_to_check.push_back(i); } // Check indices from L-N+1 up to L. Ensure indices are at least 1. for (long long i = std::max(1LL, L - N + 1); i <= L; ++i) { indices_to_check.push_back(i); } // Sort and remove duplicates if ranges overlap (unlikely needed if L > 2N, but safe). std::sort(indices_to_check.begin(), indices_to_check.end()); indices_to_check.erase(std::unique(indices_to_check.begin(), indices_to_check.end()), indices_to_check.end()); } // If N=0, A is empty, total_len is 0. The sums C_i will be 0. Max is 0. if (N == 0) { max_C = 0; first_val_set = true; } else { // Standard case N >= 1 for (long long i : indices_to_check) { // Calculate residue index `r_idx` = (i-1) mod N. This is 0-based index corresponding to A. long long r_idx = (i - 1) % N; // Check if data for this residue class `r_idx` is already computed and cached. if (cache.find(r_idx) == cache.end()) { // If not in cache map, compute it. Note: map default constructs if accessed. Check first. PrecomputedData data; // Create new data structure instance data.period_values.reserve(P); // Reserve space for efficiency data.prefix_sums.reserve(P + 1); data.prefix_sums.push_back(0); // Prefix sum of 0 elements is 0 long long current_idx = r_idx; // Start walk from index r_idx for(int k=0; k<P; ++k) { // Bounds check for A access, although current_idx guaranteed to be in [0, N-1] by modulo arithmetic long long val = A[current_idx]; data.period_values.push_back(val); data.period_sum += val; data.prefix_sums.push_back(data.period_sum); // Store prefix sum up to k-th element // Move to the next index in the sequence: (current_idx + L) mod N current_idx = (current_idx + L) % N; // Ensure positive result for modulo if intermediate potentially negative (not possible here as N,L>0) // if (current_idx < 0) current_idx += N; } data.computed = true; // Mark as computed cache[r_idx] = data; // Store computed data in cache map } // Retrieve precomputed data from cache const PrecomputedData& data = cache[r_idx]; // Calculate K_i = floor((total_len - i) / L) long long K_i = -1; // Initialize to represent invalid/empty sum range if (total_len >= i && L > 0) { // Check if i is within total length and L is positive K_i = (total_len - i) / L; } else if (total_len < i) { // If i is beyond the sequence B length K_i = -1; // Represents 0 terms } // L=0 case is excluded by constraints L >= 1. // Number of terms in the sum for C_i is K_i + 1 long long num_terms = K_i + 1; if (num_terms <= 0) { // If there are no terms in the sum for C_i long long current_C = 0; // The sum over an empty set is 0. // Update max_C if this is the first value or if 0 is greater than current max. if (!first_val_set || current_C > max_C) { max_C = current_C; first_val_set = true; // Mark that max_C is now initialized with a valid value } continue; // Move to the next index i } // Calculate number of full periods and remaining terms long long num_full_periods = num_terms / P; long long remaining_terms = num_terms % P; // Calculate the sum C_i using precomputed values long long current_C = num_full_periods * data.period_sum; // Sum from full periods // Add sum from remaining terms using prefix sums. Check bounds. if (remaining_terms >= 0 && remaining_terms < data.prefix_sums.size()) { current_C += data.prefix_sums[remaining_terms]; } else { // This path indicates an error in logic or indexing, should not happen with P>=1. // E.g. remaining_terms could be P, which is index P+1. prefix_sums has size P+1 (indices 0..P). // Index `remaining_terms` corresponds to sum of first `remaining_terms` elements. // This is correctly stored at index `remaining_terms`. } // Update the overall maximum value found so far if (!first_val_set || current_C > max_C) { max_C = current_C; first_val_set = true; // Mark that max_C holds a valid computed value } } } // End loop over indices_to_check // If N >= 1 and M >= 1, sequence B is non-empty. L >= 1. At least one C_i will have terms. // So first_val_set should be true unless N=0 case handled above. // If after all checks max_C remains at its initial very small value, it indicates an issue. // But based on constraints, at least one C_i sum will be computed. std::cout << max_C << std::endl; // Output the final maximum value return 0; }