結果
| 問題 |
No.691 E869120 and Constructing Array 5
|
| コンテスト | |
| ユーザー |
qwewe
|
| 提出日時 | 2025-05-14 13:10:11 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 7,427 bytes |
| コンパイル時間 | 1,104 ms |
| コンパイル使用メモリ | 95,476 KB |
| 実行使用メモリ | 7,848 KB |
| 最終ジャッジ日時 | 2025-05-14 13:11:47 |
| 合計ジャッジ時間 | 8,155 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | WA * 27 |
ソースコード
#include <iostream> // For input/output streams
#include <vector> // Standard library vector, though not directly used in the final logic
#include <cmath> // For mathematical functions like fabsl (absolute value for long double), sqrtl (sqrt for long double), llroundl (round to nearest long long for long double)
#include <iomanip> // For output formatting, e.g., std::fixed, std::setprecision, useful for debugging floating point values
// Use 'long double' for higher precision floating point calculations, which is crucial for this problem's accuracy requirements.
using Real = long double;
// Function to compute the square root of a 'long double' value.
// Handles potentially small negative inputs due to floating point errors by returning 0.
Real sqrt_ld(Real x) {
if (x < 0) return 0;
return sqrtl(x); // Use sqrtl from cmath for long double
}
// Function to round a 'long double' value to the nearest 'long long' integer.
// Ensures the result is non-negative, as required for the elements e_i.
long long round_ll(Real x) {
// llroundl rounds to the nearest long long integer. Ties are rounded away from zero.
long long rounded_val = llroundl(x);
// If the result of rounding is negative (can happen if x is negative), return 0,
// since e_i must be non-negative integers.
if (rounded_val < 0) return 0LL;
return rounded_val;
}
int main() {
// Optimize standard I/O operations for speed.
std::ios_base::sync_with_stdio(false); // Disable synchronization with C standard streams
std::cin.tie(NULL); // Untie cin from cout
int Q; // Number of queries
std::cin >> Q;
// Process each query
while (Q--) {
Real P; // Target value for the query
std::cin >> P;
// --- N=1 Approach ---
// Try to find a single non-negative integer k such that sqrt(k) is close to P.
Real P2 = P * P; // Calculate P squared
// Find the nearest integer k to P^2. Ensure k is non-negative.
long long k = round_ll(P2);
// Calculate the square root of k
Real sqrt_k = sqrt_ld(static_cast<Real>(k));
// Calculate the absolute difference between sqrt(k) and P
Real diff = fabsl(sqrt_k - P);
// Define the required absolute error tolerance
const Real tolerance_N1 = 1e-10L;
// Check if the error is within the tolerance
if (diff <= tolerance_N1) {
// If N=1 works, output the result: N=1 and the value k
std::cout << 1 << " " << k << "\n";
} else {
// --- N=3 Approach ---
// If N=1 fails, try to find three non-negative integers e1, e2, e3
// of the form k_i * M, such that their square roots sum up close to P.
// We use a scaling factor M = 1,000,000 = 1000^2.
const Real F = 1000.0L; // Scaling factor F = sqrt(M)
const long long M = 1000000LL; // M = F^2
// The target sum for the scaled square roots (sqrt(k_i))
Real target_T = P / F;
// The tolerance for the scaled sum is derived from the original tolerance.
// The error in P should be at most 1e-10, so error in P/F should be at most 1e-10 / F.
const Real tolerance_N3 = tolerance_N1 / F;
// Set a maximum value for k1, k2, k3 to limit the search space.
// 150 is chosen heuristically; large enough to cover expected values but small enough for performance.
const int K_max = 150;
bool found = false; // Flag to track if a solution is found
// Iterate through possible integer values for k1
for (int k1_int = 0; k1_int <= K_max; ++k1_int) {
Real k1_real = static_cast<Real>(k1_int);
Real sqrt_k1 = sqrt_ld(k1_real);
// Optimization: If sqrt(k1) alone is already too large, no need to check further.
if (sqrt_k1 > target_T + tolerance_N3) continue;
// Iterate through possible integer values for k2
for (int k2_int = 0; k2_int <= K_max; ++k2_int) {
Real k2_real = static_cast<Real>(k2_int);
Real sqrt_k2 = sqrt_ld(k2_real);
// Optimization: If sqrt(k1) + sqrt(k2) is already too large, no need to check further.
if (sqrt_k1 + sqrt_k2 > target_T + tolerance_N3) continue;
// Calculate the required value for sqrt(k3) to reach the target sum T.
Real T_prime = target_T - sqrt_k1 - sqrt_k2;
// T_prime must represent sqrt(k3), so it should be non-negative.
// Allow a tiny negative value due to floating point inaccuracies.
const Real neg_threshold = -1e-14L; // Small tolerance for negativity check
if (T_prime < neg_threshold) continue; // If substantially negative, this path is invalid.
if (T_prime < 0) T_prime = 0; // Clamp very small negatives to zero.
// Find the candidate integer k3 by rounding T_prime^2. Ensure non-negativity.
long long k3_ll = round_ll(T_prime * T_prime);
// Check if the candidate k3 is within the allowed range [0, K_max].
if (k3_ll > K_max) continue;
// Calculate the sum of square roots using the chosen k1, k2, and candidate k3.
Real k3_real = static_cast<Real>(k3_ll);
Real sqrt_k3 = sqrt_ld(k3_real);
Real S = sqrt_k1 + sqrt_k2 + sqrt_k3; // Calculated sum
// Check if the calculated sum S is within the tolerance range of the target scaled sum T.
if (fabsl(S - target_T) <= tolerance_N3) {
// If the accuracy is met, we found a solution.
// Output N=3 and the corresponding e_i values (k_i * M).
std::cout << 3 << " " << (long long)k1_int * M << " " << (long long)k2_int * M << " " << k3_ll * M << "\n";
found = true; // Set flag
goto next_query; // Use goto to break out of nested loops and proceed to next query
}
}
}
// This block is executed if the nested loops complete without finding a solution.
// According to the problem statement and structure, a solution should always be found
// either by N=1 or this N=3 strategy. If this block is reached, something unexpected happened.
if (!found) {
// Output an error message to standard error for debugging purposes.
std::cerr << "Error: Solution not found for P = " << std::fixed << std::setprecision(15) << P << std::endl;
// As a fallback, output the N=1 result (integer k) calculated earlier. Even though it failed the initial accuracy test,
// it might be the best guess or satisfy some weaker condition.
std::cout << 1 << " " << k << "\n";
}
next_query:; // Label for the goto statement
}
}
return 0; // Indicate successful execution
}
qwewe