結果
問題 |
No.2244 Integer Complete
|
ユーザー |
![]() |
提出日時 | 2025-05-14 13:04:16 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
TLE
|
実行時間 | - |
コード長 | 7,160 bytes |
コンパイル時間 | 930 ms |
コンパイル使用メモリ | 89,048 KB |
実行使用メモリ | 6,272 KB |
最終ジャッジ日時 | 2025-05-14 13:06:15 |
合計ジャッジ時間 | 5,595 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 19 TLE * 1 -- * 40 |
ソースコード
#include <iostream> #include <vector> #include <cmath> #include <numeric> // Function to compute the integer square root of a non-negative long long n. // Returns the largest integer x such that x*x <= n. // Uses binary search for efficiency and to handle large numbers correctly. long long isqrt(long long n) { // Base cases if (n < 0) return 0; // Or throw an error, but problem constraints imply non-negative values derived from positive integers. if (n == 0) return 0; // Set binary search range. // The maximum possible value of k could be large, potentially up to ~10^18. // sqrt(10^18) = 10^9. A safe upper bound is slightly larger. // 3*10^9 is sufficient since (3*10^9)^2 = 9*10^18 > max long long. long long low = 0, high = 3000000000LL; long long ans = 0; // Stores the best candidate for floor(sqrt(n)) found so far. while(low <= high) { long long mid = low + (high - low) / 2; // Calculate midpoint safely to avoid overflow. // To check mid*mid <= n without overflow, use division: mid <= n / mid // Need to handle mid == 0 case separately to avoid division by zero. if (mid == 0) { // If mid is 0, 0*0 <= n is always true for non-negative n. // ans could be 0. Move low to 1 to continue search for positive roots. ans = mid; // Update ans potentially to 0 low = 1; continue; } // Check if mid is too large (mid*mid > n) if (mid > n / mid) { high = mid - 1; // Mid is too large, search in the lower half. } else { // mid*mid <= n. Mid is a potential candidate for the integer square root. ans = mid; // Update the best candidate found so far. low = mid + 1; // Try searching for a larger root in the upper half. } } return ans; // Return the largest integer x such that x*x <= n. } // Use boolean arrays to quickly check membership in A and B. // The maximum value for A_i, B_j is 30000. Array size 30001 covers indices 1 to 30000. const int MAX_VAL = 30001; bool hasA[MAX_VAL]; // hasA[x] is true if x is in deck A bool hasB[MAX_VAL]; // hasB[x] is true if x is in deck B // Function to check if integer k can be represented as a product xy // where x is derived from some A_i and y from some B_j. // x satisfies A_i^2 <= x < (A_i+1)^2 which means A_i = floor(sqrt(x)). // y satisfies B_j^2 <= y < (B_j+1)^2 which means B_j = floor(sqrt(y)). // We need to check if k = d1 * d2 such that floor(sqrt(d1)) is in A and floor(sqrt(d2)) is in B. bool check(long long k, int max_A, int max_B) { // Find all divisors d1 of k up to sqrt(k). long long limit = isqrt(k); for (long long d1 = 1; d1 <= limit; ++d1) { if (k % d1 == 0) { // If d1 is a divisor of k long long d2 = k / d1; // The corresponding divisor d2 // Calculate integer square roots long long sqrt_d1 = isqrt(d1); long long sqrt_d2 = isqrt(d2); // Check pair (d1, d2): Does d1 correspond to an A_i and d2 to a B_j? // Check if floor(sqrt(d1)) is a value present in deck A. // Use precomputed boolean array `hasA`. Index must be within bounds [1, MAX_VAL-1]. // Also, the value must not exceed the maximum value actually present in A (max_A). bool d1_valid_for_A = (sqrt_d1 > 0 && sqrt_d1 <= max_A && sqrt_d1 < MAX_VAL && hasA[sqrt_d1]); if (d1_valid_for_A) { // Check if floor(sqrt(d2)) is a value present in deck B. bool d2_valid_for_B = (sqrt_d2 > 0 && sqrt_d2 <= max_B && sqrt_d2 < MAX_VAL && hasB[sqrt_d2]); if (d2_valid_for_B) { return true; // Found a valid representation for k } } // Check pair (d2, d1) if d1 != d2 (i.e., k is not a perfect square d1*d1) // Does d2 correspond to an A_i and d1 to a B_j? if (d1 * d1 != k) { // Check if floor(sqrt(d2)) is a value present in deck A. bool d2_valid_for_A = (sqrt_d2 > 0 && sqrt_d2 <= max_A && sqrt_d2 < MAX_VAL && hasA[sqrt_d2]); if (d2_valid_for_A) { // Check if floor(sqrt(d1)) is a value present in deck B. bool d1_valid_for_B = (sqrt_d1 > 0 && sqrt_d1 <= max_B && sqrt_d1 < MAX_VAL && hasB[sqrt_d1]); if (d1_valid_for_B) { return true; // Found a valid representation for k } } } } } // If no pair of divisors worked, k cannot be represented. return false; } int main() { // Faster I/O std::ios_base::sync_with_stdio(false); std::cin.tie(NULL); int N, M; // Number of cards in decks A and B std::cin >> N >> M; // Initialize boolean arrays tracking card presence // This is implicitly done for global arrays, but good practice to be explicit if they were local. // std::fill(hasA, hasA + MAX_VAL, false); // std::fill(hasB, hasB + MAX_VAL, false); std::vector<int> A_vec(N); // Store A values to check A[0] later int max_A = 0; // Track the maximum value in deck A for (int i = 0; i < N; ++i) { std::cin >> A_vec[i]; // Only consider positive values within the array bounds for hasA lookup table if (A_vec[i] > 0) { if (A_vec[i] < MAX_VAL) { hasA[A_vec[i]] = true; // Mark value as present in A } // Keep track of the maximum value regardless of array bounds if (A_vec[i] > max_A) max_A = A_vec[i]; } } std::vector<int> B_vec(M); // Store B values int max_B = 0; // Track the maximum value in deck B for (int i = 0; i < M; ++i) { std::cin >> B_vec[i]; if (B_vec[i] > 0) { if (B_vec[i] < MAX_VAL) { hasB[B_vec[i]] = true; // Mark value as present in B } if (B_vec[i] > max_B) max_B = B_vec[i]; } } // Handle the edge case where 1 cannot be formed. // This occurs if A does not contain 1, or B does not contain 1. // The smallest product xy would be A_1^2 * B_1^2. If A_1 > 1 or B_1 > 1, this product is > 1. // Check using the hasA/hasB arrays for presence of 1. if (!hasA[1] || !hasB[1]) { std::cout << 1 << std::endl; // If 1 cannot be formed, it's the smallest positive integer. return 0; } // Iterate through positive integers k starting from 1. // Find the first k that cannot be represented as a product xy. long long k = 1; while (true) { // Check if k can be represented. if (!check(k, max_A, max_B)) { std::cout << k << std::endl; // Found the smallest integer not representable. return 0; // Exit program. } k += 1; // Check the next integer. } return 0; // Should not be reached due to the infinite loop and return inside. }