結果
問題 |
No.1884 Sequence
|
ユーザー |
![]() |
提出日時 | 2025-05-14 13:12:58 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 54 ms / 2,000 ms |
コード長 | 7,634 bytes |
コンパイル時間 | 1,258 ms |
コンパイル使用メモリ | 98,044 KB |
実行使用メモリ | 7,936 KB |
最終ジャッジ日時 | 2025-05-14 13:13:48 |
合計ジャッジ時間 | 5,385 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 40 |
ソースコード
#include <iostream> #include <vector> #include <numeric> #include <algorithm> #include <cmath> #include <limits> // Required for std::numeric_limits // Custom GCD function for long long using Euclidean algorithm long long gcd(long long a, long long b) { // Ensure arguments are non-negative for standard GCD definition if (a < 0) a = -a; if (b < 0) b = -b; while (b) { a %= b; std::swap(a, b); } return a; } // Function to compute integer square root safely for large numbers using binary search // Returns the largest integer x such that x*x <= n. long long integer_sqrt(long long n) { if (n < 0) return 0; // Square root of negative number is not real if (n == 0) return 0; long long low = 1; // Set a safe upper bound. sqrt(10^15) is about 3.16e7. Max value of G is around 10^15. // Let's use a slightly larger bound, e.g., 2*10^9 covers sqrt(4*10^18). // Max value of long long is about 9*10^18, its sqrt is about 3*10^9. long long high = 3000000000LL; // Optimization: if n itself is smaller than initial high, adjust high. if (high > n) high = n; long long ans = 0; while(low <= high) { // Calculate mid carefully to avoid overflow long long mid = low + (high - low) / 2; // If mid is 0, something is wrong or n=0 which is handled. Avoid division by zero. if (mid == 0) break; // Check for potential overflow before multiplication mid*mid long long max_ll = std::numeric_limits<long long>::max(); // If mid > max_ll / mid, then mid*mid would overflow if (mid > max_ll / mid) { // mid is definitely too large if multiplication overflows high = mid - 1; } else if (mid * mid <= n) { // If mid*mid <= n, mid is a possible candidate for integer square root. // We want the largest such integer, so store it and try larger values. ans = mid; low = mid + 1; } else { // If mid*mid > n, mid is too large. high = mid - 1; } } return ans; // ans holds the largest integer whose square is <= n } int main() { // Faster I/O std::ios_base::sync_with_stdio(false); std::cin.tie(NULL); long long N_ll; // Read N as long long to potentially use in 64-bit calculations std::cin >> N_ll; // Convert N to int for vector size usage etc. Constraint N <= 2e5 fits in int. int N = static_cast<int>(N_ll); std::vector<long long> A(N); std::vector<long long> P; // Store positive values from A P.reserve(N); // Reserve capacity for performance for (int i = 0; i < N; ++i) { std::cin >> A[i]; if (A[i] > 0) { P.push_back(A[i]); } } int k = P.size(); // Number of positive values initially present // Case 1: If there are 0 or 1 positive values, we can always form an AP. // We can fill blanks and rearrange freely. For k=0, choose {1, 2, ..., N}. For k=1 with value p, choose {p, p+1, ..., p+N-1}. if (k <= 1) { std::cout << "Yes" << std::endl; return 0; } // Sort the positive values to identify distinct elements and check properties. std::sort(P.begin(), P.end()); // Create a vector of distinct positive values. std::vector<long long> distinct_P = P; auto last = std::unique(distinct_P.begin(), distinct_P.end()); distinct_P.erase(last, distinct_P.end()); int k_prime = distinct_P.size(); // Number of distinct positive values. // Case 2: If all positive values are identical (k_prime = 1). // We can form an AP with common difference d=0. Example: {p, p, ..., p}. // Need to fill m blanks with p. Possible if p > 0. This is guaranteed. if (k_prime == 1) { std::cout << "Yes" << std::endl; return 0; } // Case 3: If there are duplicates among positive values, but not all values are the same (k > k_prime > 1). // An AP with d != 0 must have distinct terms. An AP with d = 0 requires all terms to be equal. // Neither case works if S+ has duplicates but values are not all identical. if (k > k_prime) { std::cout << "No" << std::endl; return 0; } // Case 4: All positive values are distinct (k = k_prime >= 2). // Let the distinct sorted positive values be p_1, ..., p_k. long long p1 = distinct_P[0]; long long pk = distinct_P[k_prime - 1]; // Calculate the GCD of differences between consecutive distinct elements. // The common difference 'd' must be a divisor of this GCD. long long G = 0; // This check is logically redundant as we are in k_prime >= 2 case, but kept for clarity. if (k_prime >= 2) { G = distinct_P[1] - distinct_P[0]; for (int i = 2; i < k_prime; ++i) { G = gcd(G, distinct_P[i] - distinct_P[i-1]); // Optimization: If GCD becomes 1, it cannot get smaller. All further GCDs will be 1. if (G == 1) break; } } // If G is 0 or negative, something unexpected happened (e.g., non-distinct values passed through checks). // Since p_i are distinct and sorted, differences are positive, so G must be positive. if (G <= 0) { std::cout << "No" << std::endl; // Indicate failure or unexpected state return 0; } // Calculate the difference between the largest and smallest positive values. long long diff_pk_p1 = pk - p1; // Calculate N-1, needed for the condition check. Use N_ll for 64-bit arithmetic safety. long long N_minus_1 = N_ll - 1; // Basic check: N>=3 is given, so N-1 >= 2. N_minus_1 is positive. if (N_minus_1 <= 0) { std::cout << "No" << std::endl; // Should not happen based on constraints return 0; } // Condition for possibility: there must exist a divisor 'd' of G such that pk - p1 <= d * (N - 1). // This is equivalent to d >= ceil( (pk - p1) / (N - 1) ). // Calculate the minimum required divisor value, MinD = ceil( (pk - p1) / (N - 1) ) long long MinD; // Handle diff_pk_p1 = 0 case (means k_prime=1, already handled, but for safety) if (diff_pk_p1 == 0) { MinD = 1; // Any positive divisor d works. Require d >= 1. } else { // Calculate ceiling using integer division: (X + Y - 1) / Y for positive X, Y MinD = (diff_pk_p1 + N_minus_1 - 1) / N_minus_1; } // Since common difference d must be positive, MinD must be at least 1. // If calculation gives 0 or less, set minimum requirement to 1. if (MinD <= 0) MinD = 1; bool possible = false; // Compute integer square root of G to iterate divisors efficiently. long long sqrtG = integer_sqrt(G); // Iterate through divisors d of G up to sqrt(G). for (long long d = 1; d <= sqrtG; ++d) { if (G % d == 0) { // Check divisor d if (d >= MinD) { possible = true; break; // Found a suitable divisor, no need to check further. } // Check divisor G/d long long d2 = G / d; // Check if d2 satisfies the condition. No need to check if d2 == d separately. if (d2 >= MinD) { possible = true; break; // Found a suitable divisor } } } // Output the final result. if (possible) { std::cout << "Yes" << std::endl; } else { std::cout << "No" << std::endl; } return 0; }