-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmodint.hpp
129 lines (111 loc) · 3.22 KB
/
modint.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/**
* @file modint.hpp
* @brief Class that warps integer for modular arithmetic operations
*/
#ifndef MODINT_HPP
#define MODINT_HPP
#include <iostream>
template <std::signed_integral T = int, T MOD = 1'000'000'007> class modint;
template <std::signed_integral T, T MOD>
std::ostream &operator<<(std::ostream &, const modint<T, MOD> &);
template <std::signed_integral T, T MOD>
std::istream &operator>>(std::istream &, modint<T, MOD> &);
template <std::signed_integral T, T MOD> class modint {
private:
T x;
public:
friend std::ostream &operator<< <T, MOD>(std::ostream &, const modint &);
friend std::istream &operator>> <T, MOD>(std::istream &, modint &);
constexpr modint(const T &x) : x(x) {
if (this->x >= MOD)
this->x -= MOD;
if (this->x < 0)
this->x += MOD;
}
constexpr modint(const std::signed_integral auto &x) : modint(T(x % MOD)) {}
constexpr modint() : x{} {}
constexpr modint &operator+=(const modint &rhs) {
x += rhs.x;
if (x >= MOD)
x -= MOD;
return *this;
}
constexpr modint &operator++() { return *this += 1; }
constexpr modint operator+(const modint &rhs) const {
return modint(*this) += rhs;
}
constexpr modint operator++(int) {
modint cpy(*this);
++*this;
return cpy;
}
constexpr modint &operator-=(const modint &rhs) {
x -= rhs.x;
if (x < 0)
x += MOD;
return *this;
}
constexpr modint &operator--() { return *this -= 1; }
constexpr modint operator-(const modint &rhs) const {
return modint(*this) -= rhs;
}
constexpr modint operator-() const { return modint() - *this; }
constexpr modint operator--(int) {
modint cpy(*this);
--*this;
return cpy;
}
constexpr modint &operator*=(const modint &rhs) {
x = 1LL * x * rhs.x % MOD;
return *this;
}
constexpr modint operator*(const modint &rhs) const {
return modint(*this) *= rhs;
}
constexpr modint pow(unsigned long long p) const {
modint rt = 1, b = *this;
for (; p; p >>= 1, b *= b)
if (p & 1)
rt *= b;
return rt;
}
constexpr modint operator^(unsigned long long p) const { return pow(p); }
constexpr modint &operator^=(unsigned long long p) {
return *this = pow(p);
}
constexpr modint inv() const { return pow(MOD - 2); }
constexpr modint &operator/=(const modint &rhs) {
return *this *= rhs.inv();
}
constexpr modint operator/(const modint &rhs) const {
return modint(*this) /= rhs;
}
constexpr bool operator==(const modint &rhs) const { return x == rhs.x; }
constexpr bool operator!=(const modint &rhs) const { return x != rhs.x; }
constexpr explicit operator T() const { return x; }
constexpr explicit operator bool() const { return bool(x); }
};
template <std::signed_integral T, T MOD>
std::ostream &operator<<(std::ostream &os, const modint<T, MOD> &arg) {
return os << arg.x;
}
template <std::signed_integral T, T MOD>
std::istream &operator>>(std::istream &is, modint<T, MOD> &arg) {
is >> arg.x;
if (arg.x >= MOD)
arg.x -= MOD;
if (arg.x < 0)
arg.x += MOD;
return is;
}
using mint_1097 = modint<>;
using mint_1099 = modint<int, 1'000'000'009>;
using mint_998 = modint<int, 998'244'353>;
namespace std {
template <class T, T MOD> struct hash<modint<T, MOD>> {
size_t operator()(const modint<T, MOD> &s) const noexcept {
return hash<T>{}(T(s));
}
};
} // namespace std
#endif