Skip to content

Commit 19509cd

Browse files
authored
Merge pull request #77 from qryxip/doc-for-math
Add document for `math`
2 parents 0b88690 + 581d951 commit 19509cd

File tree

1 file changed

+107
-0
lines changed

1 file changed

+107
-0
lines changed

src/math.rs

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,31 @@
1+
//! Number-theoretic algorithms.
2+
13
use crate::internal_math;
24

35
use 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)]
630
pub 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+
/// ```
2470
pub 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+
/// ```
31115
pub 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+
/// ```
81188
pub 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

Comments
 (0)