atcoder/lib/math/
mod_int.rs1use std::fmt::{self, Display};
4use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
29pub struct ModInt<const MOD: i64> {
30 value: i64,
31}
32
33impl<const MOD: i64> ModInt<MOD> {
34 pub fn new(value: i64) -> Self {
41 assert!(MOD > 0, "modulus must be positive");
42 Self {
43 value: value.rem_euclid(MOD),
44 }
45 }
46
47 pub const fn value(self) -> i64 {
49 self.value
50 }
51
52 pub const fn val(&self) -> i64 {
56 self.value
57 }
58
59 pub fn inv(self) -> Self {
66 self.pow(MOD - 2)
67 }
68
69 pub fn pow(self, mut exponent: i64) -> Self {
78 assert!(exponent >= 0, "exponent must be non-negative");
79 let mut result = 1_i64;
80 let mut base = self.value;
81 while exponent > 0 {
82 if exponent & 1 == 1 {
83 result = result * base % MOD;
84 }
85 base = base * base % MOD;
86 exponent >>= 1;
87 }
88 Self::new(result)
89 }
90}
91
92impl<const MOD: i64> Display for ModInt<MOD> {
93 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
94 self.value.fmt(formatter)
95 }
96}
97
98impl<const MOD: i64> Add for ModInt<MOD> {
99 type Output = Self;
100 fn add(self, rhs: Self) -> Self::Output {
101 Self::new(self.value + rhs.value)
102 }
103}
104
105impl<const MOD: i64> Sub for ModInt<MOD> {
106 type Output = Self;
107 fn sub(self, rhs: Self) -> Self::Output {
108 Self::new(self.value - rhs.value)
109 }
110}
111
112impl<const MOD: i64> Mul for ModInt<MOD> {
113 type Output = Self;
114 fn mul(self, rhs: Self) -> Self::Output {
115 Self::new(self.value * rhs.value)
116 }
117}
118
119impl<const MOD: i64> Div for ModInt<MOD> {
120 type Output = Self;
121 #[allow(clippy::suspicious_arithmetic_impl)]
122 fn div(self, rhs: Self) -> Self::Output {
123 self * rhs.inv()
124 }
125}
126
127impl<const MOD: i64> AddAssign for ModInt<MOD> {
128 fn add_assign(&mut self, rhs: Self) {
129 *self = *self + rhs;
130 }
131}
132
133impl<const MOD: i64> SubAssign for ModInt<MOD> {
134 fn sub_assign(&mut self, rhs: Self) {
135 *self = *self - rhs;
136 }
137}
138
139impl<const MOD: i64> MulAssign for ModInt<MOD> {
140 fn mul_assign(&mut self, rhs: Self) {
141 *self = *self * rhs;
142 }
143}
144
145impl<const MOD: i64> DivAssign for ModInt<MOD> {
146 fn div_assign(&mut self, rhs: Self) {
147 *self = *self / rhs;
148 }
149}
150
151pub type Mod998 = ModInt<998_244_353>;
153pub type Mod107 = ModInt<1_000_000_007>;
155
156#[cfg(test)]
157mod tests {
158 use super::Mod998;
159
160 #[test]
161 fn normalizes_and_calculates() {
162 assert_eq!(Mod998::new(-1).value(), 998_244_352);
163 assert_eq!((Mod998::new(2) / Mod998::new(2)).value(), 1);
164 assert_eq!(Mod998::new(2).pow(10).value(), 1024);
165 }
166}