1+ //! Number-theoretic algorithms.
2+
13use crate :: internal_math;
24
35use std:: mem:: swap;
46
7+ /// Returns $x^n \bmod m$.
8+ ///
9+ /// # Constraints
10+ ///
11+ /// - $0 \leq n$
12+ /// - $1 \leq m$
13+ ///
14+ /// # Panics
15+ ///
16+ /// Panics if the above constraints are not satisfied.
17+ ///
18+ /// # Complexity
19+ ///
20+ /// - $O(\log n)$
21+ ///
22+ /// # Example
23+ ///
24+ /// ```
25+ /// use ac_library_rs::math;
26+ ///
27+ /// assert_eq!(math::pow_mod(2, 10000, 7), 2);
28+ /// ```
529#[ allow( clippy:: many_single_char_names) ]
630pub fn pow_mod ( x : i64 , mut n : i64 , m : u32 ) -> u32 {
731 assert ! ( 0 <= n && 1 <= m && m <= 2u32 . pow( 31 ) ) ;
@@ -21,13 +45,73 @@ pub fn pow_mod(x: i64, mut n: i64, m: u32) -> u32 {
2145 r
2246}
2347
48+ /// Returns an integer $y \in [0, m)$ such that $xy \equiv 1 \pmod m$.
49+ ///
50+ /// # Constraints
51+ ///
52+ /// - $\gcd(x, m) = 1$
53+ /// - $1 \leq m$
54+ ///
55+ /// # Panics
56+ ///
57+ /// Panics if the above constraints are not satisfied.
58+ ///
59+ /// # Complexity
60+ ///
61+ /// - $O(\log m)$
62+ ///
63+ /// # Example
64+ ///
65+ /// ```
66+ /// use ac_library_rs::math;
67+ ///
68+ /// assert_eq!(math::inv_mod(3, 7), 5);
69+ /// ```
2470pub fn inv_mod ( x : i64 , m : i64 ) -> i64 {
2571 assert ! ( 1 <= m) ;
2672 let z = internal_math:: inv_gcd ( x, m) ;
2773 assert ! ( z. 0 == 1 ) ;
2874 z. 1
2975}
3076
77+ /// Performs CRT (Chinese Remainder Theorem).
78+ ///
79+ /// Given two sequences $r, m$ of length $n$, this function solves the modular equation system
80+ ///
81+ /// \\[
82+ /// x \equiv r_i \pmod{m_i}, \forall i \in \\{0, 1, \cdots, n - 1\\}
83+ /// \\]
84+ ///
85+ /// If there is no solution, it returns $(0, 0)$.
86+ ///
87+ /// Otherwise, all of the solutions can be written as the form $x \equiv y \pmod z$, using integer $y, z\\ (0 \leq y < z = \text{lcm}(m))$.
88+ /// It returns this $(y, z)$.
89+ ///
90+ /// If $n = 0$, it returns $(0, 1)$.
91+ ///
92+ /// # Constraints
93+ ///
94+ /// - $|r| = |m|$
95+ /// - $1 \leq m_{\forall i}$
96+ /// - $\text{lcm}(m)$ is in `i64`
97+ ///
98+ /// # Panics
99+ ///
100+ /// Panics if the above constraints are not satisfied.
101+ ///
102+ /// # Complexity
103+ ///
104+ /// - $O(n \log \text{lcm}(m))$
105+ ///
106+ /// # Example
107+ ///
108+ /// ```
109+ /// use ac_library_rs::math;
110+ ///
111+ /// let r = [2, 3, 2];
112+ /// let m = [3, 5, 7];
113+ /// assert_eq!(math::crt(&r, &m), (23, 105));
114+ /// ```
31115pub fn crt ( r : & [ i64 ] , m : & [ i64 ] ) -> ( i64 , i64 ) {
32116 assert_eq ! ( r. len( ) , m. len( ) ) ;
33117 // Contracts: 0 <= r0 < m0
@@ -78,6 +162,29 @@ pub fn crt(r: &[i64], m: &[i64]) -> (i64, i64) {
78162 ( r0, m0)
79163}
80164
165+ /// Returns $\sum_{i = 0}^{n - 1} \lfloor \frac{a \times i + b}{m} \rfloor$.
166+ ///
167+ /// # Constraints
168+ ///
169+ /// - $0 \leq n \leq 10^9$
170+ /// - $1 \leq m \leq 10^9$
171+ /// - $0 \leq a, b \leq m$
172+ ///
173+ /// # Panics
174+ ///
175+ /// Panics if the above constraints are not satisfied and overflow or division by zero occurred.
176+ ///
177+ /// # Complexity
178+ ///
179+ /// - $O(\log(n + m + a + b))$
180+ ///
181+ /// # Example
182+ ///
183+ /// ```
184+ /// use ac_library_rs::math;
185+ ///
186+ /// assert_eq!(math::floor_sum(6, 5, 4, 3), 13);
187+ /// ```
81188pub fn floor_sum ( n : i64 , m : i64 , mut a : i64 , mut b : i64 ) -> i64 {
82189 let mut ans = 0 ;
83190 if a >= m {
0 commit comments