This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub hitonanode/cplib-cpp
#define PROBLEM "https://judge.yosupo.jp/problem/rational_approximation" #include "../rational_approximation.hpp" #include <cassert> #include <iostream> using namespace std; int main() { cin.tie(nullptr), ios::sync_with_stdio(false); int T; cin >> T; while (T--) { int N, x, y; cin >> N >> x >> y; const auto [l, r] = rational_approximation<int>(N, x, y); const auto [lnum, lden] = l; const auto [rnum, rden] = r; cout << lnum << ' ' << lden << ' ' << rnum << ' ' << rden << '\n'; } }
#line 1 "number/test/rational_approximation.test.cpp" #define PROBLEM "https://judge.yosupo.jp/problem/rational_approximation" #line 2 "number/rational_approximation.hpp" #include <cassert> #include <utility> #include <vector> // Rational approximation based on Stern–Brocot tree // Input: N > 0, num >= 0, den >= 0 (num > 0 or den > 0) // return {{p, q}, {r, s}} where p/q <= num/den <= r/s. Strictly, // - p/q = max(n / d | n / d <= num / den, 0 <= n <= N, 1 <= d <= N) // - r/s = min(n / d | num / den <= n / d, 0 <= n <= N, 1 <= d <= N) template <class Int> std::pair<std::pair<Int, Int>, std::pair<Int, Int>> rational_approximation(Int N, Int num, Int den) { assert(N >= 1); assert(num >= 0); assert(den >= 0); assert(num > 0 or den > 0); if (num == Int(0)) return {{Int(0), Int(1)}, {Int(0), Int(1)}}; // 0 if (den == Int(0)) return {{Int(1), Int(0)}, {Int(1), Int(0)}}; // inf // p/q <= num/den <= r/s Int p = 0, q = 1, r = 1, s = 0; bool is_left = false; while (true) { Int max_steps = num / den; if (is_left) { // r + steps * p <= N // s + steps * q <= N if (p > Int(0)) max_steps = std::min(max_steps, (N - r) / p); max_steps = std::min(max_steps, (N - s) / q); r += max_steps * p; s += max_steps * q; } else { // p + steps * r <= N // q + steps * s <= N max_steps = std::min(max_steps, (N - p) / r); if (s > Int(0)) max_steps = std::min(max_steps, (N - q) / s); p += max_steps * r; q += max_steps * s; } if (is_left and !max_steps) break; num -= max_steps * den; if (num == Int(0)) { if (is_left) { return {{r, s}, {r, s}}; } else { return {{p, q}, {p, q}}; } } std::swap(num, den); is_left = !is_left; } return {{p, q}, {r, s}}; } #line 3 "number/test/rational_approximation.test.cpp" #line 5 "number/test/rational_approximation.test.cpp" #include <iostream> using namespace std; int main() { cin.tie(nullptr), ios::sync_with_stdio(false); int T; cin >> T; while (T--) { int N, x, y; cin >> N >> x >> y; const auto [l, r] = rational_approximation<int>(N, x, y); const auto [lnum, lden] = l; const auto [rnum, rden] = r; cout << lnum << ' ' << lden << ' ' << rnum << ' ' << rden << '\n'; } }