5#include <unordered_map>
7#include "cplib/num/bmint.hpp"
8#include "cplib/num/gcd.hpp"
9#include "cplib/port/bit.hpp"
16template <
typename ModInt>
17std::optional<typename ModInt::int_type> discrete_log_coprime_modint(ModInt g, ModInt x) {
18 using T =
typename ModInt::int_type;
19 const T n = ModInt::mod(), m = std::ceil(std::sqrt(n));
20 std::unordered_map<T, T> table;
22 for (T i = 1; i <= m; i++) {
24 table.try_emplace(s.residue(), i);
27 for (T i = 0; i < m; i++) {
28 if (
auto it = table.find(x.residue()); it != table.end()) {
29 return i * m + it->second;
38std::pair<int, T> discrete_log_naive(T g, T x, T n,
int t) {
42 using bmint = BarrettModInt<DynamicBarrettReductionContext<T>>;
43 auto _guard = bmint::set_mod_guard(n);
45 for (
int i = 1; i <= t; i++) {
51 return {-1, my.val()};
67template <
typename T, std::enable_if_t<std::is_
unsigned_v<T>>* =
nullptr>
72 const int t = port::bit_width(n) - 1;
73 auto [k, y] = impl::discrete_log_naive(g, x, n, t);
85 auto _guard = mint::set_mod_guard(n / d);
86 if (
auto ret = impl::discrete_log_coprime_modint(mint(g), mint(x) / mint(y))) {
87 return ret.value() + t;
Modular integer using Barrett reduction.
Definition: bmint.hpp:111
constexpr T gcd(T x, T y)
Greatest common divisor.
Definition: gcd.hpp:21
std::optional< T > discrete_log(T g, T x, T n)
Modular discrete logarithm.
Definition: discrete_log.hpp:68