|
| 1 | +#ifndef MP_LIBRARY_MODINT_HPP |
| 2 | +#define MP_LIBRARY_MODINT_HPP |
| 3 | +#include <iostream> |
| 4 | +#include <mrpython/numeric.hpp> |
| 5 | +#include <type_traits> |
| 6 | + |
| 7 | +namespace mrpython { |
| 8 | +template <unsigned P> class modint { |
| 9 | + static_assert(P > 0, "modint: P must be positive"); |
| 10 | + static_assert(P < (1U << 31), "modint: P must be less than 2^31"); |
| 11 | + |
| 12 | + unsigned int v; |
| 13 | + |
| 14 | + public: |
| 15 | + template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>> |
| 16 | + constexpr modint(T x) |
| 17 | + : v((std::is_unsigned<T>::value |
| 18 | + ? static_cast<unsigned int>(x % static_cast<T>(P)) |
| 19 | + : static_cast<unsigned int>((x % static_cast<T>(P) + P) % P))) {} |
| 20 | + constexpr modint(void): v(0) {} |
| 21 | + constexpr modint& operator+=(modint x) { |
| 22 | + if ((this->v += x.v) >= P) this->v -= P; |
| 23 | + return *this; |
| 24 | + } |
| 25 | + constexpr modint& operator-=(modint x) { |
| 26 | + if (this->v < x.v) this->v += P; |
| 27 | + this->v -= x.v; |
| 28 | + return *this; |
| 29 | + } |
| 30 | + constexpr modint& operator*=(unsigned int x) { |
| 31 | + this->v = (unsigned long long int)this->v * x % P; |
| 32 | + return *this; |
| 33 | + } |
| 34 | + template <typename T, |
| 35 | + typename = std::enable_if_t<std::is_integral<T>::value && |
| 36 | + !std::is_same<T, unsigned int>::value>> |
| 37 | + constexpr modint& operator*=(T x) { |
| 38 | + return *this *= modint(x); |
| 39 | + } |
| 40 | + constexpr modint& operator*=(modint x) { |
| 41 | + this->v = (unsigned long long int)this->v * x.v % P; |
| 42 | + return *this; |
| 43 | + } |
| 44 | + constexpr modint& operator/=(modint x) { return *this *= x.inv(); } |
| 45 | + constexpr friend modint operator+(modint a, modint b) { |
| 46 | + a += b; |
| 47 | + return a; |
| 48 | + } |
| 49 | + constexpr friend modint operator-(modint a, modint b) { |
| 50 | + a -= b; |
| 51 | + return a; |
| 52 | + } |
| 53 | + template <typename T, |
| 54 | + typename = std::enable_if_t<std::is_same<T, modint>::value || |
| 55 | + std::is_integral<T>::value>> |
| 56 | + constexpr friend modint operator*(modint a, T b) { |
| 57 | + a *= b; |
| 58 | + return a; |
| 59 | + } |
| 60 | + template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>> |
| 61 | + constexpr friend modint operator*(T a, modint b) { |
| 62 | + b *= a; |
| 63 | + return b; |
| 64 | + } |
| 65 | + constexpr friend modint operator/(modint a, modint b) { return a /= b; } |
| 66 | + constexpr modint operator-(void) const { return modint() - *this; } |
| 67 | + constexpr unsigned int val(void) const { return v; } |
| 68 | + constexpr friend std::ostream& operator<<(std::ostream& out, modint x) { |
| 69 | + return out << x.v; |
| 70 | + } |
| 71 | + constexpr modint inv(void) const { return mrpython::fastPow(*this, P - 2); } |
| 72 | + constexpr modint pow(unsigned long long int n) const { |
| 73 | + return mrpython::fastPow(*this, n); |
| 74 | + } |
| 75 | + static constexpr unsigned modval() { return P; } |
| 76 | +}; |
| 77 | +} // namespace mrpython |
| 78 | +#endif // MP_LIBRARY_MODINT_HPP |
0 commit comments