1
1
#ifndef CP_ALGO_ALGEBRA_MODINT_HPP
2
2
#define CP_ALGO_ALGEBRA_MODINT_HPP
3
- #include " ../random/rng.hpp"
4
- #include " affine.hpp"
5
3
#include " common.hpp"
6
- #include < algorithm>
7
4
#include < iostream>
8
- #include < optional>
9
5
namespace cp_algo ::algebra {
10
6
template <typename modint>
11
7
struct modint_base {
12
- // Would make it virtual, but it affects avx...
13
- int mod () const {
14
- if constexpr (modint::static_mod) {
15
- return modint::static_mod;
16
- } else {
17
- return static_cast <modint*>(this )->mod ();
18
- }
8
+ static int mod () {
9
+ return modint::mod ();
19
10
}
20
11
modint_base (): r(0 ) {}
21
12
modint_base (int64_t rr): r(rr % mod()) {
22
13
r = std::min (r, r + mod ());
23
14
}
24
15
modint inv () const {
25
- return bpow (static_cast <modint const &>(* this ), mod () - 2 );
16
+ return bpow (to_modint ( ), mod () - 2 );
26
17
}
27
18
modint operator - () const {return std::min (-r, mod () - r);}
28
- modint& operator /= (const modint &t) {return *this *= t.inv ();}
19
+ modint& operator /= (const modint &t) {
20
+ return to_modint () *= t.inv ();
21
+ }
29
22
modint& operator *= (const modint &t) {
30
- r *= t.r ; r %= mod ();
31
- return static_cast <modint&>(* this );
23
+ r *= t.r ; if ( mod ()) { r %= mod ();}
24
+ return to_modint ( );
32
25
}
33
26
modint& operator += (const modint &t) {
34
27
r += t.r ; r = std::min (r, r - mod ());
35
- return static_cast <modint&>(* this );
28
+ return to_modint ( );
36
29
}
37
30
modint& operator -= (const modint &t) {
38
31
r -= t.r ; r = std::min (r, r + mod ());
39
- return static_cast <modint&>(*this );
40
- }
41
- modint operator + (const modint &t) const {
42
- return modint (static_cast <modint const &>(*this )) += t;
43
- }
44
- modint operator - (const modint &t) const {
45
- return modint (static_cast <modint const &>(*this )) -= t;
46
- }
47
- modint operator * (const modint &t) const {
48
- return modint (static_cast <modint const &>(*this )) *= t;
49
- }
50
- modint operator / (const modint &t) const {
51
- return modint (static_cast <modint const &>(*this )) /= t;
32
+ return to_modint ();
52
33
}
34
+ modint operator + (const modint &t) const {return modint (to_modint ()) += t;}
35
+ modint operator - (const modint &t) const {return modint (to_modint ()) -= t;}
36
+ modint operator * (const modint &t) const {return modint (to_modint ()) *= t;}
37
+ modint operator / (const modint &t) const {return modint (to_modint ()) /= t;}
53
38
auto operator <=> (const modint_base &t) const = default ;
54
39
explicit operator int () const {return r;}
55
40
int64_t rem () const {return 2 * r > (uint64_t )mod () ? r - mod () : r;}
@@ -62,12 +47,14 @@ namespace cp_algo::algebra {
62
47
if (r >= (uint64_t )mod ()) {
63
48
r %= mod ();
64
49
}
65
- return static_cast <modint&>(* this );
50
+ return to_modint ( );
66
51
}
67
52
uint64_t & setr () {return r;}
68
53
uint64_t getr () const {return r;}
69
54
private:
70
55
uint64_t r;
56
+ modint& to_modint () {return static_cast <modint&>(*this );}
57
+ modint const & to_modint () const {return static_cast <modint const &>(*this );}
71
58
};
72
59
template <typename modint>
73
60
std::istream& operator >> (std::istream &in, modint_base<modint> &x) {
@@ -81,28 +68,19 @@ namespace cp_algo::algebra {
81
68
82
69
template <int m>
83
70
struct modint : modint_base<modint<m>> {
84
- constexpr static int static_mod = m;
71
+ static constexpr int mod () { return m;}
85
72
using Base = modint_base<modint<m>>;
86
73
using Base::Base;
87
- constexpr static uint64_t static_modmod = 8LL *m*m;
88
74
};
89
75
90
76
struct dynamic_modint : modint_base<dynamic_modint> {
91
- constexpr static int static_mod = 0 ;
77
+ static int mod () {return m;}
78
+ static void switch_mod (int nm) {m = nm;}
92
79
using Base = modint_base<dynamic_modint>;
93
- int mod () const {return m;}
94
- dynamic_modint (dynamic_modint const & t): Base(t), m(t.m) {}
95
- dynamic_modint (int m, int64_t r): m(m) {
96
- setr () = r % m;
97
- setr () = std::min (setr (), setr () + mod ());
98
- }
99
- static auto GF (int mod) {
100
- return [mod](int64_t r) {
101
- return dynamic_modint (mod, r);
102
- };
103
- }
80
+ using Base::Base;
104
81
private:
105
- int m;
82
+ static int m;
106
83
};
84
+ int dynamic_modint::m = 0 ;
107
85
}
108
86
#endif // CP_ALGO_ALGEBRA_MODINT_HPP
0 commit comments