This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub kmyk/competitive-programming-library
#define PROBLEM "https://yukicoder.me/problems/no/1255" #include <cassert> #include <cstdint> #include <iostream> #include <tuple> #include <utility> #include "../utils/macros.hpp" #include "../modulus/modinv.hpp" #include "../modulus/modlog.hpp" using namespace std; int64_t solve(int64_t n) { if (n == 1) return 1; if (n == 2) return 2; assert (n >= 3); int64_t m = 2 * n - 1; auto f = [&](int64_t aq, int64_t ar, int64_t bq, int64_t br) { int64_t cq = aq + bq; int64_t cr = ar + br; if (cr >= m) { cr -= m; cq += 1; } return make_pair(cq, cr); }; int64_t k = modlog(2, modinv(2, m), m) + 1; int64_t q0 = 0; int64_t r0 = 0; int64_t q1 = 0; int64_t r1 = 1; REP (i, 60) { if (k & (1ll << i)) { tie(q0, r0) = f(q0, r0, q1, r1); } tie(q1, r1) = f(q1, r1, q1, r1); } return k + q0; } int main() { int t; cin >> t; while (t --) { int64_t n; cin >> n; cout << solve(n) << endl; } return 0; }
#line 1 "modulus/modlog.yuki1255.test.cpp" #define PROBLEM "https://yukicoder.me/problems/no/1255" #include <cassert> #include <cstdint> #include <iostream> #include <tuple> #include <utility> #line 2 "utils/macros.hpp" #define REP(i, n) for (int i = 0; (i) < (int)(n); ++ (i)) #define REP3(i, m, n) for (int i = (m); (i) < (int)(n); ++ (i)) #define REP_R(i, n) for (int i = (int)(n) - 1; (i) >= 0; -- (i)) #define REP3R(i, m, n) for (int i = (int)(n) - 1; (i) >= (int)(m); -- (i)) #define ALL(x) std::begin(x), std::end(x) #line 2 "modulus/modinv.hpp" #include <algorithm> #line 5 "modulus/modinv.hpp" inline int32_t modinv_nocheck(int32_t value, int32_t MOD) { assert (0 <= value and value < MOD); if (value == 0) return -1; int64_t a = value, b = MOD; int64_t x = 0, y = 1; for (int64_t u = 1, v = 0; a; ) { int64_t q = b / a; x -= q * u; std::swap(x, u); y -= q * v; std::swap(y, v); b -= q * a; std::swap(b, a); } if (not (value * x + MOD * y == b and b == 1)) return -1; if (x < 0) x += MOD; assert (0 <= x and x < MOD); return x; } inline int32_t modinv(int32_t x, int32_t MOD) { int32_t y = modinv_nocheck(x, MOD); assert (y != -1); return y; } #line 3 "modulus/modlog.hpp" #include <climits> #include <cmath> #line 6 "modulus/modlog.hpp" #include <unordered_map> #line 4 "modulus/modpow.hpp" inline int32_t modpow(uint_fast64_t x, uint64_t k, int32_t MOD) { assert (/* 0 <= x and */ x < (uint_fast64_t)MOD); uint_fast64_t y = 1; for (; k; k >>= 1) { if (k & 1) (y *= x) %= MOD; (x *= x) %= MOD; } assert (/* 0 <= y and */ y < (uint_fast64_t)MOD); return y; } #line 11 "modulus/modlog.hpp" /** * @brief discrete log / 離散対数 (the baby-step giant-step, $O(\sqrt{m})$) * @description find the smallest $x \ge 0$ s.t. $g^x \equiv y \pmod{m}$ * @param m is a positive integer * @note -1 if not found */ inline int modlog(int g, int y, int m) { assert (0 <= g and g < m); assert (0 <= y and y < m); if (m == 1) return 0; if (y == 1) return 0; if (g == 0 and y == 0) return 1; // meet-in-the-middle; let x = a \sqrt{m} + b int sqrt_m = sqrt(m) + 100; // + 100 is required to bruteforce g^b for b < 100; this avoids problems with g != 0 and y = 0 assert (sqrt_m >= 0); // baby-step: list (y, gy, g^2 y, ...) = (g^x, g^{x + 1}, g^{x + 2}, ...) std::unordered_map<int, int> table; int baby = 1; REP (b, sqrt_m) { if (baby == y) return b; table[(int64_t)baby * y % m] = b; baby = (int64_t)baby * g % m; } // giant-step: list (g^{sqrt(m)}, g^{2 sqrt(m)}, g^{3 sqrt(m)}, ...) int giant = 1; REP3 (a, 1, sqrt_m + 3) { giant = (int64_t)giant * baby % m; auto it = table.find(giant); if (it != table.end()) { int b = it->second; int x = (int64_t)a * sqrt_m - b; assert (x >= 0); return (modpow(g, x, m) == y ? x : -1); } } return -1; } #line 10 "modulus/modlog.yuki1255.test.cpp" using namespace std; int64_t solve(int64_t n) { if (n == 1) return 1; if (n == 2) return 2; assert (n >= 3); int64_t m = 2 * n - 1; auto f = [&](int64_t aq, int64_t ar, int64_t bq, int64_t br) { int64_t cq = aq + bq; int64_t cr = ar + br; if (cr >= m) { cr -= m; cq += 1; } return make_pair(cq, cr); }; int64_t k = modlog(2, modinv(2, m), m) + 1; int64_t q0 = 0; int64_t r0 = 0; int64_t q1 = 0; int64_t r1 = 1; REP (i, 60) { if (k & (1ll << i)) { tie(q0, r0) = f(q0, r0, q1, r1); } tie(q1, r1) = f(q1, r1, q1, r1); } return k + q0; } int main() { int t; cin >> t; while (t --) { int64_t n; cin >> n; cout << solve(n) << endl; } return 0; }