Asa's CP Library

a01sa01to's competitive programming library. Requires C++20 or higher with GCC. This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub a01sa01to/cp-library

:heavy_check_mark: Modint
(library/data-structure/modint.hpp)

概要

剰余環 $\mathbb{Z}/m\mathbb{Z}$ 上の演算を行うための構造体。 加減乗除、べき乗、逆元の演算ができる。

使い方

コンストラクタとか

それ以外は一緒。

制約

計算量

Tip

$m$ が固定ならコンパイル時計算をするので多少高速に計算可能。

Depends on

Verified with

Code

#pragma once

#include <cassert>
#include <concepts>
#include <numeric>
#include <stdexcept>
#include <type_traits>
using namespace std;

#include "../_internal/modint-base.hpp"
#include "../math/extgcd.hpp"

namespace asalib::ds {
  template<unsigned int mod>
    requires(mod >= 1)
  class static_modint: _internal::modint_base {
    using mint = static_modint;
    using uint = unsigned int;
    using ll = long long;
    using ull = unsigned long long;

    public:
    constexpr static_modint(): _val(0) {};

    template<integral T>
    constexpr static_modint(const T& x) {
      if constexpr (is_signed_v<T>) {
        ll y = x % static_cast<ll>(mod);
        if (y < 0) y += mod;
        _val = y;
      }
      else {
        _val = x % mod;
      }
    }

    friend constexpr mint operator+(const mint& l, const mint& r) { return mint(l) += r; }
    friend constexpr mint operator-(const mint& l, const mint& r) { return mint(l) -= r; }
    friend constexpr mint operator*(const mint& l, const mint& r) { return mint(l) *= r; }
    friend constexpr mint operator/(const mint& l, const mint& r) { return mint(l) /= r; }
    constexpr mint operator+() const { return *this; }
    constexpr mint operator-() const { return 0 - *this; }

    constexpr mint& operator+=(const mint& other) {
      _val += other._val;
      if (_val >= mod) _val -= mod;
      return *this;
    }
    constexpr mint& operator-=(const mint& other) {
      _val -= other._val;
      if (_val >= mod) _val += mod;
      return *this;
    }
    constexpr mint& operator*=(const mint& other) {
      ull z = _val;
      z *= other._val;
      _val = z % mod;
      return *this;
    }
    constexpr mint& operator/=(const mint& other) { return *this = *this * other.inv(); }

    constexpr mint& operator++() {
      _val++;
      if (_val == mod) _val = 0;
      return *this;
    }
    constexpr mint& operator--() {
      if (_val == 0) _val = mod;
      _val--;
      return *this;
    }
    constexpr mint operator++(int) {
      mint res = *this;
      ++*this;
      return res;
    }
    constexpr mint operator--(int) {
      mint res = *this;
      --*this;
      return res;
    }

    constexpr bool operator==(const mint& r) const { return _val == r._val; }
    constexpr bool operator!=(const mint& r) const { return _val != r._val; }
    constexpr bool operator<(const mint& r) const { return _val < r._val; }

    template<integral T>
    constexpr mint pow(T x) const {
      assert(x >= 0);
      mint res = 1, base = *this;
      while (x) {
        if (x & 1) res *= base;
        base *= base;
        x >>= 1;
      }
      return res;
    }

    constexpr mint inv() const {
      if constexpr (is_prime_mod) return pow(mod - 2);
      else {
        if (gcd(_val, mod) != 1) throw invalid_argument("Modular inverse does not exist");
        return mint(math::extgcd<long long>(_val, mod, 1).value().first);
      }
    }

    constexpr unsigned int val() const { return _val; }

    private:
    uint _val;
    static constexpr bool is_prime_mod = []() {
      for (unsigned int i = 2; i * i <= mod; ++i) {
        if (mod % i == 0) return false;
      }
      return true;
    }();
  };

  template<unsigned int _id>
  class dynamic_modint: _internal::modint_base {
    using mint = dynamic_modint;
    using uint = unsigned int;
    using ll = long long;
    using ull = unsigned long long;

    public:
    constexpr dynamic_modint(): _val(0) {}

    template<integral T>
    constexpr dynamic_modint(const T& x) {
      assert(_mod >= 1);
      if constexpr (is_signed_v<T>) {
        ll y = x % static_cast<ll>(_mod);
        if (y < 0) y += _mod;
        _val = y;
      }
      else {
        _val = x % _mod;
      }
    };

    friend constexpr auto operator+(const mint& l, const mint& r) -> mint { return mint(l) += r; }
    friend constexpr mint operator-(const mint& l, const mint& r) { return mint(l) -= r; }
    friend constexpr mint operator*(const mint& l, const mint& r) { return mint(l) *= r; }
    friend constexpr mint operator/(const mint& l, const mint& r) { return mint(l) /= r; }
    constexpr mint operator+() const { return *this; }
    constexpr mint operator-() const { return 0 - *this; }

    constexpr mint& operator+=(const mint& other) {
      _val += other._val;
      if (_val >= _mod) _val -= _mod;
      return *this;
    }
    constexpr mint& operator-=(const mint& other) {
      _val -= other._val;
      if (_val >= _mod) _val += _mod;
      return *this;
    }
    constexpr mint& operator*=(const mint& other) {
      ull z = _val;
      z *= other._val;
      _val = z % _mod;
      return *this;
    }
    constexpr mint& operator/=(const mint& other) { return *this = *this * other.inv(); }

    constexpr mint& operator++() {
      _val++;
      if (_val == _mod) _val = 0;
      return *this;
    }
    constexpr mint& operator--() {
      if (_val == 0) _val = _mod;
      _val--;
      return *this;
    }
    constexpr mint operator++(int) {
      mint res = *this;
      ++*this;
      return res;
    }
    constexpr mint operator--(int) {
      mint res = *this;
      --*this;
      return res;
    }

    constexpr bool operator==(const mint& r) const { return _val == r._val; }
    constexpr bool operator!=(const mint& r) const { return _val != r._val; }
    constexpr bool operator<(const mint& r) const { return _val < r._val; }

    template<integral T>
    constexpr mint pow(T x) const {
      assert(x >= 0);
      mint res = 1, base = *this;
      while (x) {
        if (x & 1) res *= base;
        base *= base;
        x >>= 1;
      }
      return res;
    }

    constexpr mint inv() const {
      if (gcd(_val, _mod) != 1) throw invalid_argument("Modular inverse does not exist");
      return mint(math::extgcd<long long>(_val, _mod, 1).value().first);
    }

    constexpr uint val() const { return _val; }
    constexpr static uint mod() { return _mod; }
    constexpr static void set_mod(const uint mod) {
      assert(mod >= 1);
      _mod = mod;
    }

    private:
    uint _val;
    static inline uint _mod;
  };
}  // namespace asalib::ds
#line 2 "library/data-structure/modint.hpp"

#include <cassert>
#include <concepts>
#include <numeric>
#include <stdexcept>
#include <type_traits>
using namespace std;

#line 2 "library/_internal/modint-base.hpp"

#line 4 "library/_internal/modint-base.hpp"
using namespace std;

namespace asalib::_internal {
  class modint_base {};

  template<typename T>
  concept is_modint = is_base_of_v<modint_base, T>;
}  // namespace asalib::_internal
#line 2 "library/math/extgcd.hpp"

#line 4 "library/math/extgcd.hpp"
#include <optional>
#include <utility>
using namespace std;

namespace asalib::math {
  // Returns a pair (x, y) such that ax + by = c
  template<integral T>
  constexpr optional<pair<T, T>> extgcd(T a, T b, T c) {
    if (b == 0) {
      if (c % a != 0) return nullopt;
      return make_pair(c / a, 0);
    }
    auto res = extgcd(b, a % b, c);
    if (!res) return nullopt;
    auto [x, y] = *res;
    return make_pair(y, x - (a / b) * y);
  }
}  // namespace asalib::math
#line 12 "library/data-structure/modint.hpp"

namespace asalib::ds {
  template<unsigned int mod>
    requires(mod >= 1)
  class static_modint: _internal::modint_base {
    using mint = static_modint;
    using uint = unsigned int;
    using ll = long long;
    using ull = unsigned long long;

    public:
    constexpr static_modint(): _val(0) {};

    template<integral T>
    constexpr static_modint(const T& x) {
      if constexpr (is_signed_v<T>) {
        ll y = x % static_cast<ll>(mod);
        if (y < 0) y += mod;
        _val = y;
      }
      else {
        _val = x % mod;
      }
    }

    friend constexpr mint operator+(const mint& l, const mint& r) { return mint(l) += r; }
    friend constexpr mint operator-(const mint& l, const mint& r) { return mint(l) -= r; }
    friend constexpr mint operator*(const mint& l, const mint& r) { return mint(l) *= r; }
    friend constexpr mint operator/(const mint& l, const mint& r) { return mint(l) /= r; }
    constexpr mint operator+() const { return *this; }
    constexpr mint operator-() const { return 0 - *this; }

    constexpr mint& operator+=(const mint& other) {
      _val += other._val;
      if (_val >= mod) _val -= mod;
      return *this;
    }
    constexpr mint& operator-=(const mint& other) {
      _val -= other._val;
      if (_val >= mod) _val += mod;
      return *this;
    }
    constexpr mint& operator*=(const mint& other) {
      ull z = _val;
      z *= other._val;
      _val = z % mod;
      return *this;
    }
    constexpr mint& operator/=(const mint& other) { return *this = *this * other.inv(); }

    constexpr mint& operator++() {
      _val++;
      if (_val == mod) _val = 0;
      return *this;
    }
    constexpr mint& operator--() {
      if (_val == 0) _val = mod;
      _val--;
      return *this;
    }
    constexpr mint operator++(int) {
      mint res = *this;
      ++*this;
      return res;
    }
    constexpr mint operator--(int) {
      mint res = *this;
      --*this;
      return res;
    }

    constexpr bool operator==(const mint& r) const { return _val == r._val; }
    constexpr bool operator!=(const mint& r) const { return _val != r._val; }
    constexpr bool operator<(const mint& r) const { return _val < r._val; }

    template<integral T>
    constexpr mint pow(T x) const {
      assert(x >= 0);
      mint res = 1, base = *this;
      while (x) {
        if (x & 1) res *= base;
        base *= base;
        x >>= 1;
      }
      return res;
    }

    constexpr mint inv() const {
      if constexpr (is_prime_mod) return pow(mod - 2);
      else {
        if (gcd(_val, mod) != 1) throw invalid_argument("Modular inverse does not exist");
        return mint(math::extgcd<long long>(_val, mod, 1).value().first);
      }
    }

    constexpr unsigned int val() const { return _val; }

    private:
    uint _val;
    static constexpr bool is_prime_mod = []() {
      for (unsigned int i = 2; i * i <= mod; ++i) {
        if (mod % i == 0) return false;
      }
      return true;
    }();
  };

  template<unsigned int _id>
  class dynamic_modint: _internal::modint_base {
    using mint = dynamic_modint;
    using uint = unsigned int;
    using ll = long long;
    using ull = unsigned long long;

    public:
    constexpr dynamic_modint(): _val(0) {}

    template<integral T>
    constexpr dynamic_modint(const T& x) {
      assert(_mod >= 1);
      if constexpr (is_signed_v<T>) {
        ll y = x % static_cast<ll>(_mod);
        if (y < 0) y += _mod;
        _val = y;
      }
      else {
        _val = x % _mod;
      }
    };

    friend constexpr auto operator+(const mint& l, const mint& r) -> mint { return mint(l) += r; }
    friend constexpr mint operator-(const mint& l, const mint& r) { return mint(l) -= r; }
    friend constexpr mint operator*(const mint& l, const mint& r) { return mint(l) *= r; }
    friend constexpr mint operator/(const mint& l, const mint& r) { return mint(l) /= r; }
    constexpr mint operator+() const { return *this; }
    constexpr mint operator-() const { return 0 - *this; }

    constexpr mint& operator+=(const mint& other) {
      _val += other._val;
      if (_val >= _mod) _val -= _mod;
      return *this;
    }
    constexpr mint& operator-=(const mint& other) {
      _val -= other._val;
      if (_val >= _mod) _val += _mod;
      return *this;
    }
    constexpr mint& operator*=(const mint& other) {
      ull z = _val;
      z *= other._val;
      _val = z % _mod;
      return *this;
    }
    constexpr mint& operator/=(const mint& other) { return *this = *this * other.inv(); }

    constexpr mint& operator++() {
      _val++;
      if (_val == _mod) _val = 0;
      return *this;
    }
    constexpr mint& operator--() {
      if (_val == 0) _val = _mod;
      _val--;
      return *this;
    }
    constexpr mint operator++(int) {
      mint res = *this;
      ++*this;
      return res;
    }
    constexpr mint operator--(int) {
      mint res = *this;
      --*this;
      return res;
    }

    constexpr bool operator==(const mint& r) const { return _val == r._val; }
    constexpr bool operator!=(const mint& r) const { return _val != r._val; }
    constexpr bool operator<(const mint& r) const { return _val < r._val; }

    template<integral T>
    constexpr mint pow(T x) const {
      assert(x >= 0);
      mint res = 1, base = *this;
      while (x) {
        if (x & 1) res *= base;
        base *= base;
        x >>= 1;
      }
      return res;
    }

    constexpr mint inv() const {
      if (gcd(_val, _mod) != 1) throw invalid_argument("Modular inverse does not exist");
      return mint(math::extgcd<long long>(_val, _mod, 1).value().first);
    }

    constexpr uint val() const { return _val; }
    constexpr static uint mod() { return _mod; }
    constexpr static void set_mod(const uint mod) {
      assert(mod >= 1);
      _mod = mod;
    }

    private:
    uint _val;
    static inline uint _mod;
  };
}  // namespace asalib::ds
Back to top page