CompetitiveProgrammingCpp

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub

:heavy_check_mark: Test/Math/BabyStepGiantStep.test.cpp

Depends on

Code

#define PROBLEM "https://judge.yosupo.jp/problem/discrete_logarithm_mod"

#include <iostream>

#include <ranges>


// begin:tag includes

#include "../../Library/Math/BabyStepGiantStep.hpp"

// end:tag includes


using ll = long long;

signed main() {
  std::cin.tie(0);
  std::ios::sync_with_stdio(0);

  int t;
  std::cin >> t;
  for ([[maybe_unused]] auto _ : std::views::iota(0, t)) {
    ll x, y, m;
    std::cin >> x >> y >> m;

    auto ans = (m == 1)
                   ? 0
                   : mtd::baby_step_giant_step<std::hash<ll>>(
                         x, ll(1), y, m - 1,
                         [&](ll _x, ll _y) { return (_x * _y) % m; },
                         [&](const ll _m, ll _x) { return (_m * _x) % m; });

    if (ans) {
      std::cout << ans.value() << std::endl;
    } else {
      std::cout << -1 << std::endl;
    }
  }
}
#line 1 "Test/Math/BabyStepGiantStep.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/discrete_logarithm_mod"

#include <iostream>

#include <ranges>


// begin:tag includes

#line 2 "Library/Math/BabyStepGiantStep.hpp"

#include <cmath>
#include <optional>
#line 6 "Library/Math/BabyStepGiantStep.hpp"
#include <unordered_set>

namespace mtd {
  /*
   * x^i * s = t (0 <= i < n) を満たす最小のi
   * O(sqrt(n))
   */
  template <class Hash, class Monoid, class T, class Product, class Op>
  std::optional<long long> baby_step_giant_step(const Monoid& x, const T& s,
                                                const T& t, long long n,
                                                const Product prod,
                                                const Op& op) {
    if (n == 0) { return (s == t) ? std::make_optional(0) : std::nullopt; }
    if (n == 1) {
      return (s == t)          ? std::make_optional(0)
             : (op(x, s) == t) ? std::make_optional(1)
                               : std::nullopt;
    }

    auto m = static_cast<long long>(std::sqrt(n));
    std::unordered_set<T, Hash> mp;
    auto xm = x;
    for (auto i : std::views::iota(0, m)) {
      mp.emplace(op(xm, t));
      if (i < m - 1) { xm = prod(xm, x); }
    }

    bool find = false;
    auto xks = s;
    for (auto k : std::views::iota(1, n / m + 5)) {
      auto next = op(xm, xks);
      if (mp.contains(next)) {
        auto xi = xks;
        for (auto i : std::views::iota(m * (k - 1), m * k + 1)) {
          if (xi == t) { return i; }
          xi = op(x, xi);
        }
        if (find) { return std::nullopt; }
        find = true;
      }
      std::swap(xks, next);
    }
    return std::nullopt;
  }
};  // namespace mtd
#line 8 "Test/Math/BabyStepGiantStep.test.cpp"
// end:tag includes


using ll = long long;

signed main() {
  std::cin.tie(0);
  std::ios::sync_with_stdio(0);

  int t;
  std::cin >> t;
  for ([[maybe_unused]] auto _ : std::views::iota(0, t)) {
    ll x, y, m;
    std::cin >> x >> y >> m;

    auto ans = (m == 1)
                   ? 0
                   : mtd::baby_step_giant_step<std::hash<ll>>(
                         x, ll(1), y, m - 1,
                         [&](ll _x, ll _y) { return (_x * _y) % m; },
                         [&](const ll _m, ll _x) { return (_m * _x) % m; });

    if (ans) {
      std::cout << ans.value() << std::endl;
    } else {
      std::cout << -1 << std::endl;
    }
  }
}
Back to top page