1use crate::internal_math;
4
5use std::mem::swap;
6
7#[allow(clippy::many_single_char_names)]
30pub fn pow_mod(x: i64, mut n: i64, m: u32) -> u32 {
31 assert!(0 <= n && 1 <= m && m <= 2u32.pow(31));
32 if m == 1 {
33 return 0;
34 }
35 let bt = internal_math::Barrett::new(m);
36 let mut r = 1;
37 let mut y = internal_math::safe_mod(x, m as i64) as u32;
38 while n != 0 {
39 if n & 1 != 0 {
40 r = bt.mul(r, y);
41 }
42 y = bt.mul(y, y);
43 n >>= 1;
44 }
45 r
46}
47
48pub fn inv_mod(x: i64, m: i64) -> i64 {
71 assert!(1 <= m);
72 let z = internal_math::inv_gcd(x, m);
73 assert!(z.0 == 1);
74 z.1
75}
76
77pub fn crt(r: &[i64], m: &[i64]) -> (i64, i64) {
116 assert_eq!(r.len(), m.len());
117 let (mut r0, mut m0) = (0, 1);
119 for (&(mut ri), &(mut mi)) in r.iter().zip(m.iter()) {
120 assert!(1 <= mi);
121 ri = internal_math::safe_mod(ri, mi);
122 if m0 < mi {
123 swap(&mut r0, &mut ri);
124 swap(&mut m0, &mut mi);
125 }
126 if m0 % mi == 0 {
127 if r0 % mi != ri {
128 return (0, 0);
129 }
130 continue;
131 }
132 let (g, im) = internal_math::inv_gcd(m0, mi);
143 let u1 = mi / g;
144 if (ri - r0) % g != 0 {
146 return (0, 0);
147 }
148 let x = (ri - r0) / g % u1 * im % u1;
150
151 r0 += x * m0;
156 m0 *= u1; if r0 < 0 {
158 r0 += m0
159 };
160 }
161
162 (r0, m0)
163}
164
165pub fn floor_sum(n: i64, m: i64, mut a: i64, mut b: i64) -> i64 {
189 let mut ans = 0;
190 if a >= m {
191 ans += (n - 1) * n * (a / m) / 2;
192 a %= m;
193 }
194 if b >= m {
195 ans += n * (b / m);
196 b %= m;
197 }
198
199 let y_max = (a * n + b) / m;
200 let x_max = y_max * m - b;
201 if y_max == 0 {
202 return ans;
203 }
204 ans += (n - (x_max + a - 1) / a) * y_max;
205 ans += floor_sum(y_max, a, m, (a - x_max % a) % a);
206 ans
207}
208
209#[cfg(test)]
210mod tests {
211 #![allow(clippy::unreadable_literal)]
212 #![allow(clippy::cognitive_complexity)]
213 use super::*;
214 #[test]
215 fn test_pow_mod() {
216 assert_eq!(pow_mod(0, 0, 1), 0);
217 assert_eq!(pow_mod(0, 0, 3), 1);
218 assert_eq!(pow_mod(0, 0, 723), 1);
219 assert_eq!(pow_mod(0, 0, 998244353), 1);
220 assert_eq!(pow_mod(0, 0, 2u32.pow(31)), 1);
221
222 assert_eq!(pow_mod(0, 1, 1), 0);
223 assert_eq!(pow_mod(0, 1, 3), 0);
224 assert_eq!(pow_mod(0, 1, 723), 0);
225 assert_eq!(pow_mod(0, 1, 998244353), 0);
226 assert_eq!(pow_mod(0, 1, 2u32.pow(31)), 0);
227
228 assert_eq!(pow_mod(0, i64::max_value(), 1), 0);
229 assert_eq!(pow_mod(0, i64::max_value(), 3), 0);
230 assert_eq!(pow_mod(0, i64::max_value(), 723), 0);
231 assert_eq!(pow_mod(0, i64::max_value(), 998244353), 0);
232 assert_eq!(pow_mod(0, i64::max_value(), 2u32.pow(31)), 0);
233
234 assert_eq!(pow_mod(1, 0, 1), 0);
235 assert_eq!(pow_mod(1, 0, 3), 1);
236 assert_eq!(pow_mod(1, 0, 723), 1);
237 assert_eq!(pow_mod(1, 0, 998244353), 1);
238 assert_eq!(pow_mod(1, 0, 2u32.pow(31)), 1);
239
240 assert_eq!(pow_mod(1, 1, 1), 0);
241 assert_eq!(pow_mod(1, 1, 3), 1);
242 assert_eq!(pow_mod(1, 1, 723), 1);
243 assert_eq!(pow_mod(1, 1, 998244353), 1);
244 assert_eq!(pow_mod(1, 1, 2u32.pow(31)), 1);
245
246 assert_eq!(pow_mod(1, i64::max_value(), 1), 0);
247 assert_eq!(pow_mod(1, i64::max_value(), 3), 1);
248 assert_eq!(pow_mod(1, i64::max_value(), 723), 1);
249 assert_eq!(pow_mod(1, i64::max_value(), 998244353), 1);
250 assert_eq!(pow_mod(1, i64::max_value(), 2u32.pow(31)), 1);
251
252 assert_eq!(pow_mod(i64::max_value(), 0, 1), 0);
253 assert_eq!(pow_mod(i64::max_value(), 0, 3), 1);
254 assert_eq!(pow_mod(i64::max_value(), 0, 723), 1);
255 assert_eq!(pow_mod(i64::max_value(), 0, 998244353), 1);
256 assert_eq!(pow_mod(i64::max_value(), 0, 2u32.pow(31)), 1);
257
258 assert_eq!(pow_mod(i64::max_value(), i64::max_value(), 1), 0);
259 assert_eq!(pow_mod(i64::max_value(), i64::max_value(), 3), 1);
260 assert_eq!(pow_mod(i64::max_value(), i64::max_value(), 723), 640);
261 assert_eq!(
262 pow_mod(i64::max_value(), i64::max_value(), 998244353),
263 683296792
264 );
265 assert_eq!(
266 pow_mod(i64::max_value(), i64::max_value(), 2u32.pow(31)),
267 2147483647
268 );
269
270 assert_eq!(pow_mod(2, 3, 1_000_000_007), 8);
271 assert_eq!(pow_mod(5, 7, 1_000_000_007), 78125);
272 assert_eq!(pow_mod(123, 456, 1_000_000_007), 565291922);
273 }
274
275 #[test]
276 #[should_panic]
277 fn test_inv_mod_1() {
278 inv_mod(271828, 0);
279 }
280
281 #[test]
282 #[should_panic]
283 fn test_inv_mod_2() {
284 inv_mod(3141592, 1000000008);
285 }
286
287 #[test]
288 fn test_crt() {
289 let a = [44, 23, 13];
290 let b = [13, 50, 22];
291 assert_eq!(crt(&a, &b), (1773, 7150));
292 let a = [12345, 67890, 99999];
293 let b = [13, 444321, 95318];
294 assert_eq!(crt(&a, &b), (103333581255, 550573258014));
295 let a = [0, 3, 4];
296 let b = [1, 9, 5];
297 assert_eq!(crt(&a, &b), (39, 45));
298 }
299
300 #[test]
301 fn test_floor_sum() {
302 assert_eq!(floor_sum(0, 1, 0, 0), 0);
303 assert_eq!(floor_sum(1_000_000_000, 1, 1, 1), 500_000_000_500_000_000);
304 assert_eq!(
305 floor_sum(1_000_000_000, 1_000_000_000, 999_999_999, 999_999_999),
306 499_999_999_500_000_000
307 );
308 assert_eq!(floor_sum(332955, 5590132, 2231, 999423), 22014575);
309 }
310}