/***************************************************************************** * Subdividing a Land * * Programmed by T.Yoshino *****************************************************************************/ #include #include #include using namespace std; //#define DEBUG 1 //#define USE_GMPXX 1 //#define USE_GMP_N 1 #ifdef USE_GMPXX #include #endif//USE_GMPXX /***************************************************************************** * Typedefs *****************************************************************************/ /** Type for N */ #if defined(USE_GMPXX) && defined(USE_GMP_N) // Use multi-precision integer for N's values typedef mpz_class ntype; #else //!(defined(USE_GMPXX) && defined(USE_GMP_N)) // Simply use int for N's values typedef int ntype; // requires sqrt() operation static inline ntype sqrt(const ntype N) { return (int) floor(sqrt((double) N)); } #endif//!(defined(USE_GMPXX) && defined(USE_GMP_N)) /** Type for answer values */ #ifdef USE_GMPXX typedef mpz_class rtype; #else //!USE_GMPXX typedef long long rtype; #endif//!USE_GMPXX /** Type for answers */ typedef pair anstype; /***************************************************************************** * Program Body *****************************************************************************/ /** * Solve Pell's equation |x^2 - N y^2| = 1. * Here N must not be a quadratic number. * * @param N The value of N * @return Answer pair (x, y) */ static anstype solve_pell(const ntype N) { const ntype k0 = sqrt(N); ntype g = 0, h = 1, k = k0; // g(0), h(0), k(0) // (xp, yp) and (x, y) contain alpha(n-1) and alpha(n), respectively. rtype yp = 1, y = 0, xp = 0, x = 1; // And initial value is for n = 0. #ifdef DEBUG int count = 0; #endif//DEBUG do { #ifdef DEBUG cout << "--- Iteration " << count++ << " ---" << endl; cout << "g = " << g << ", h = " << h << ", k = " << k << endl; cout << "x = " << x << ", y = " << y << endl; cout << "rhs = " << (x * x - N * y * y) << endl; #endif // g(n+1), h(n+1), k(n+1) calculation // Using: g(n+1) = -g(n) + k(n)*h(n) // h(n+1) = (N - g(n+1)^2) / h(n) // k(n+1) = floor((k0 + g(n+1)) / h(n+1)) // Here it is assured that g(n) <= k0, 0 < h(n) <= N, 0 < k(n) <= 2 k0. ntype ng = -g + k * h, nh = (N - ng * ng) / h, nk = (k0 + ng) / nh; // alpha(n+1) calculation (in-place) // Using: alpha(n+1) = alpha(n-1) + k(n) * alpha(n) // alpha(n+1) is strictly larger than alpha(n) for all n >= 0. xp += k * x, yp += k * y; // Now (xp, yp) holds alpha(n+1) // Prepare for the next round g = ng, h = nh, k = nk; swap(x, xp), swap(y, yp); } while(h > 1); #ifdef DEBUG cout << "--- Iteration " << count << " ---" << endl; cout << "g = " << g << ", h = " << h << ", k = " << k << endl; cout << "x = " << x << ", y = " << y << endl; cout << "rhs = " << (x * x - N * y * y) << endl; #endif // Here |x^2 - N y^2| = h(n) == 1 is already assured, so even if we use a // limited precision of integer representation, overflow is not a problem. if (x * x - N * y * y < 0) { // answer = alpha(n)^2 > alpha(n). rtype nx = x * x + N * y * y, ny = 2 * x * y; x = nx, y = ny; #ifdef DEBUG cout << "--- Postprocess needed ---" << endl; cout << "x = " << x << ", y = " << y << endl; cout << "rhs = " << (x * x - N * y * y) << endl; #endif//DEBUG } return anstype(x, y); } /** * Toplevel for solving the problem * * @param N The value of N for a case * @return Answer pair */ static anstype solve(ntype N) { const ntype sqN = sqrt(N *= 2); if (sqN * sqN == N) { // 2N is perfect square #ifdef DEBUG cout << "2N is perfect square of " << sqN << endl; #endif//DEBUG return anstype(rtype(sqN), rtype(1)); } else { return solve_pell(N); } } /***************************************************************************** * Bootstrap *****************************************************************************/ int main() { ntype N; int ncase = 0; while (cin >> N, N > 0) { const anstype result = solve(N); cout << "Case " << ++ncase << ": " << result.first << ' ' << result.second << endl; } }