Mod logarithm
(Mylib/Number/Mod/mod_log.cpp)
Operations
-
mod_log(a, b, n)
- $a^x = b \pmod m$を満たす
x
を求める。
- Time complexity $O(\sqrt m)$
Requirements
Notes
Problems
References
Depends on
Verified with
Code
#pragma once
#include <cmath>
#include <numeric>
#include <optional>
#include <unordered_map>
#include "Mylib/Number/Mod/mod_inv.cpp"
#include "Mylib/Number/Mod/mod_pow.cpp"
namespace haar_lib {
std::optional<int64_t> mod_log(int64_t a, int64_t b, int64_t m) {
if (b == 1) return 0;
int64_t d = 0;
while (1) {
if (auto g = std::gcd(a, m); g != 1) {
if (b % g != 0) return {};
d += 1;
m /= g;
b /= g;
(b *= mod_inv(a / g, m)) %= m;
if (b == 1) return d;
} else {
break;
}
}
const int64_t sq = std::sqrt(m) + 1;
std::unordered_map<int64_t, int64_t> mp;
{
int64_t t = 1 % m;
for (int i = 0; i < sq; ++i) {
if (mp.find(t) == mp.end()) mp[t] = i;
(t *= a) %= m;
}
}
{
int64_t A = mod_pow(mod_inv(a, m), sq, m);
int64_t t = b % m;
for (int i = 0; i < sq; ++i) {
if (mp.find(t) != mp.end()) {
int64_t ret = i * sq + mp[t] + d;
return ret;
}
(t *= A) %= m;
}
}
return {};
}
} // namespace haar_lib
#line 2 "Mylib/Number/Mod/mod_log.cpp"
#include <cmath>
#include <numeric>
#include <optional>
#include <unordered_map>
#line 2 "Mylib/Number/Mod/mod_inv.cpp"
#include <cstdint>
#include <utility>
namespace haar_lib {
constexpr int64_t mod_inv(int64_t a, int64_t m) {
int64_t b = m, u = 1, v = 0;
while (b) {
int64_t t = a / b;
a -= t * b;
a = a ^ b;
b = a ^ b;
a = a ^ b;
u -= t * v;
u = u ^ v;
v = u ^ v;
u = u ^ v;
}
u %= m;
if (u < 0) u += m;
return u;
}
} // namespace haar_lib
#line 3 "Mylib/Number/Mod/mod_pow.cpp"
namespace haar_lib {
constexpr int64_t mod_pow(int64_t n, int64_t p, int64_t m) {
int64_t ret = 1;
while (p > 0) {
if (p & 1) (ret *= n) %= m;
(n *= n) %= m;
p >>= 1;
}
return ret;
}
} // namespace haar_lib
#line 8 "Mylib/Number/Mod/mod_log.cpp"
namespace haar_lib {
std::optional<int64_t> mod_log(int64_t a, int64_t b, int64_t m) {
if (b == 1) return 0;
int64_t d = 0;
while (1) {
if (auto g = std::gcd(a, m); g != 1) {
if (b % g != 0) return {};
d += 1;
m /= g;
b /= g;
(b *= mod_inv(a / g, m)) %= m;
if (b == 1) return d;
} else {
break;
}
}
const int64_t sq = std::sqrt(m) + 1;
std::unordered_map<int64_t, int64_t> mp;
{
int64_t t = 1 % m;
for (int i = 0; i < sq; ++i) {
if (mp.find(t) == mp.end()) mp[t] = i;
(t *= a) %= m;
}
}
{
int64_t A = mod_pow(mod_inv(a, m), sq, m);
int64_t t = b % m;
for (int i = 0; i < sq; ++i) {
if (mp.find(t) != mp.end()) {
int64_t ret = i * sq + mp[t] + d;
return ret;
}
(t *= A) %= m;
}
}
return {};
}
} // namespace haar_lib
Back to top page