This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub Luzhiled/syakyo-library
#include "src/math/modular-arithmetic/mod-log.hpp"
#pragma once #include <numeric> #include <map> #include "src/cpp-template/header/int-alias.hpp" namespace luz { // calculate minimum x s.t. a^{x} = b (mod p), // return -1 if answer is not exists. i64 mod_log(i64 a, i64 b, i64 p) { i64 g = 1; for (i64 i = p; i; i /= 2) (g *= a) %= p; g = std::gcd(g, p); i64 t = 1, c = 0; while (t % g) { if (t == b) return c; (t *= a) %= p; c++; } if (b % g) return -1; t /= g; b /= g; i64 n = p / g, h = 0, gs = 1; while (h * h < n) { (gs *= a) %= n; h++; } std::unordered_map< i64, i64 > bs; for (i64 s = 0, e = b; s < h; bs[e] = ++s) { (e *= a) %= n; } for (i64 s = 0, e = t; s < n;) { (e *= gs) %= n; s += h; if (bs.count(e)) return c + s - bs[e]; } return -1; } }
#line 2 "src/math/modular-arithmetic/mod-log.hpp" #include <numeric> #include <map> #line 2 "src/cpp-template/header/int-alias.hpp" #include <cstdint> namespace luz { using i32 = std::int32_t; using i64 = std::int64_t; using u32 = std::uint32_t; using u64 = std::uint64_t; } #line 7 "src/math/modular-arithmetic/mod-log.hpp" namespace luz { // calculate minimum x s.t. a^{x} = b (mod p), // return -1 if answer is not exists. i64 mod_log(i64 a, i64 b, i64 p) { i64 g = 1; for (i64 i = p; i; i /= 2) (g *= a) %= p; g = std::gcd(g, p); i64 t = 1, c = 0; while (t % g) { if (t == b) return c; (t *= a) %= p; c++; } if (b % g) return -1; t /= g; b /= g; i64 n = p / g, h = 0, gs = 1; while (h * h < n) { (gs *= a) %= n; h++; } std::unordered_map< i64, i64 > bs; for (i64 s = 0, e = b; s < h; bs[e] = ++s) { (e *= a) %= n; } for (i64 s = 0, e = t; s < n;) { (e *= gs) %= n; s += h; if (bs.count(e)) return c + s - bs[e]; } return -1; } }