@@ -16,35 +16,36 @@ namespace cp_algo::math {
16
16
template <typename modint, typename _Int>
17
17
struct modint_base {
18
18
using Int = _Int;
19
- using Uint = std::make_unsigned_t <Int>;
19
+ using UInt = std::make_unsigned_t <Int>;
20
20
static constexpr size_t bits = sizeof (Int) * 8 ;
21
- using Int2 = std::conditional_t <bits <= 32 , uint64_t , __uint128_t >;
21
+ using Int2 = std::conditional_t <bits <= 32 , int64_t , __int128_t >;
22
+ using UInt2 = std::conditional_t <bits <= 32 , uint64_t , __uint128_t >;
22
23
static Int mod () {
23
24
return modint::mod ();
24
25
}
25
- static Uint imod () {
26
+ static UInt imod () {
26
27
return modint::imod ();
27
28
}
28
- static Int2 pw128 () {
29
+ static UInt2 pw128 () {
29
30
return modint::pw128 ();
30
31
}
31
- static Uint m_reduce (Int2 ab) {
32
+ static UInt m_reduce (UInt2 ab) {
32
33
if (mod () % 2 == 0 ) [[unlikely]] {
33
34
return ab % mod ();
34
35
} else {
35
- Uint m = ab * imod ();
36
- return (ab + (Int2 )m * mod ()) >> bits;
36
+ UInt m = ab * imod ();
37
+ return (ab + (UInt2 )m * mod ()) >> bits;
37
38
}
38
39
}
39
- static Uint m_transform (Uint a) {
40
+ static UInt m_transform (UInt a) {
40
41
if (mod () % 2 == 0 ) [[unlikely]] {
41
42
return a;
42
43
} else {
43
44
return m_reduce (a * pw128 ());
44
45
}
45
46
}
46
47
modint_base (): r(0 ) {}
47
- modint_base (Int rr): r(rr % mod()) {
48
+ modint_base (Int2 rr): r(rr % mod()) {
48
49
r = std::min (r, r + mod ());
49
50
r = m_transform (r);
50
51
}
@@ -60,7 +61,7 @@ namespace cp_algo::math {
60
61
return to_modint () *= t.inv ();
61
62
}
62
63
modint& operator *= (const modint &t) {
63
- r = m_reduce ((Int2 )r * t.r );
64
+ r = m_reduce ((UInt2 )r * t.r );
64
65
return to_modint ();
65
66
}
66
67
modint& operator += (const modint &t) {
@@ -83,37 +84,37 @@ namespace cp_algo::math {
83
84
auto operator < (const modint_base &t) const {return getr () < t.getr ();}
84
85
auto operator > (const modint_base &t) const {return getr () > t.getr ();}
85
86
Int rem () const {
86
- Uint R = getr ();
87
- return 2 * R > (Uint )mod () ? R - mod () : R;
87
+ UInt R = getr ();
88
+ return 2 * R > (UInt )mod () ? R - mod () : R;
88
89
}
89
90
90
91
// Only use if you really know what you're doing!
91
- Uint modmod () const {return (Uint )8 * mod () * mod ();};
92
- void add_unsafe (Uint t) {r += t;}
92
+ UInt modmod () const {return (UInt )8 * mod () * mod ();};
93
+ void add_unsafe (UInt t) {r += t;}
93
94
void pseudonormalize () {r = std::min (r, r - modmod ());}
94
95
modint const & normalize () {
95
- if (r >= (Uint )mod ()) {
96
+ if (r >= (UInt )mod ()) {
96
97
r %= mod ();
97
98
}
98
99
return to_modint ();
99
100
}
100
- void setr (Uint rr) {r = m_transform (rr);}
101
- Uint getr () const {
102
- Uint res = m_reduce (r);
101
+ void setr (UInt rr) {r = m_transform (rr);}
102
+ UInt getr () const {
103
+ UInt res = m_reduce (r);
103
104
return std::min (res, res - mod ());
104
105
}
105
- void setr_direct (Uint rr) {r = rr;}
106
- Uint getr_direct () const {return r;}
106
+ void setr_direct (UInt rr) {r = rr;}
107
+ UInt getr_direct () const {return r;}
107
108
private:
108
- Uint r;
109
+ UInt r;
109
110
modint& to_modint () {return static_cast <modint&>(*this );}
110
111
modint const & to_modint () const {return static_cast <modint const &>(*this );}
111
112
};
112
113
template <typename modint>
113
114
concept modint_type = std::is_base_of_v<modint_base<modint, typename modint::Int>, modint>;
114
115
template <modint_type modint>
115
116
std::istream& operator >> (std::istream &in, modint &x) {
116
- typename modint::Uint r;
117
+ typename modint::UInt r;
117
118
auto &res = in >> r;
118
119
x.setr (r);
119
120
return res;
@@ -127,24 +128,24 @@ namespace cp_algo::math {
127
128
struct modint : modint_base<modint<m>, decltype (m)> {
128
129
using Base = modint_base<modint<m>, decltype (m)>;
129
130
using Base::Base;
130
- static constexpr Base::Uint im = m % 2 ? inv2(-m) : 0 ;
131
- static constexpr Base::Uint r2 = (typename Base::Int2 )(-1 ) % m + 1 ;
131
+ static constexpr Base::UInt im = m % 2 ? inv2(-m) : 0 ;
132
+ static constexpr Base::UInt r2 = (typename Base::UInt2 )(-1 ) % m + 1 ;
132
133
static constexpr Base::Int mod () {return m;}
133
- static constexpr Base::Uint imod () {return im;}
134
- static constexpr Base::Int2 pw128 () {return r2;}
134
+ static constexpr Base::UInt imod () {return im;}
135
+ static constexpr Base::UInt2 pw128 () {return r2;}
135
136
};
136
137
137
138
template <typename Int = int64_t >
138
139
struct dynamic_modint : modint_base<dynamic_modint<Int>, Int> {
139
140
using Base = modint_base<dynamic_modint<Int>, Int>;
140
141
using Base::Base;
141
142
static Int mod () {return m;}
142
- static Base::Uint imod () {return im;}
143
- static Base::Int2 pw128 () {return r2;}
143
+ static Base::UInt imod () {return im;}
144
+ static Base::UInt2 pw128 () {return r2;}
144
145
static void switch_mod (Int nm) {
145
146
m = nm;
146
147
im = m % 2 ? inv2 (-m) : 0 ;
147
- r2 = (typename Base::Int2 )(-1 ) % m + 1 ;
148
+ r2 = (typename Base::UInt2 )(-1 ) % m + 1 ;
148
149
}
149
150
150
151
// Wrapper for temp switching
@@ -158,13 +159,13 @@ namespace cp_algo::math {
158
159
}
159
160
private:
160
161
static Int m;
161
- static Base::Uint im, r1, r2;
162
+ static Base::UInt im, r1, r2;
162
163
};
163
164
template <typename Int>
164
165
Int dynamic_modint<Int>::m = 1 ;
165
166
template <typename Int>
166
- dynamic_modint<Int>::Base::Uint dynamic_modint<Int>::im = -1 ;
167
+ dynamic_modint<Int>::Base::UInt dynamic_modint<Int>::im = -1 ;
167
168
template <typename Int>
168
- dynamic_modint<Int>::Base::Uint dynamic_modint<Int>::r2 = 0 ;
169
+ dynamic_modint<Int>::Base::UInt dynamic_modint<Int>::r2 = 0 ;
169
170
}
170
171
#endif // CP_ALGO_MATH_MODINT_HPP
0 commit comments