atcoder/lib/math/
sieve.rs1#[derive(Debug, Clone)]
27pub struct Sieve {
28 smallest_prime_factor: Vec<usize>,
29}
30
31impl Sieve {
32 pub fn new(limit: usize) -> Self {
36 let mut smallest_prime_factor: Vec<usize> = (0..=limit).collect();
37
38 for prime in 2..=limit {
39 if smallest_prime_factor[prime] != prime {
41 continue;
42 }
43
44 if prime > limit / prime {
46 continue;
47 }
48
49 for multiple in (prime * prime..=limit).step_by(prime) {
52 if smallest_prime_factor[multiple] == multiple {
53 smallest_prime_factor[multiple] = prime;
54 }
55 }
56 }
57
58 Self {
59 smallest_prime_factor,
60 }
61 }
62
63 pub fn limit(&self) -> usize {
65 self.smallest_prime_factor.len() - 1
66 }
67
68 pub fn is_prime(&self, n: usize) -> bool {
76 self.assert_in_range(n);
77
78 n >= 2 && self.smallest_prime_factor[n] == n
79 }
80
81 pub fn primes(&self) -> impl Iterator<Item = usize> + '_ {
86 (2..=self.limit()).filter(|&n| self.smallest_prime_factor[n] == n)
87 }
88
89 pub fn prime_factorize(&self, mut n: usize) -> Vec<(usize, usize)> {
99 assert!(n > 0, "zero does not have a prime factorization");
100
101 self.assert_in_range(n);
102
103 let mut factors = Vec::new();
104
105 while n > 1 {
106 let prime = self.smallest_prime_factor[n];
107 let mut exponent = 0;
108
109 while n % prime == 0 {
110 n /= prime;
111 exponent += 1;
112 }
113
114 factors.push((prime, exponent));
115 }
116
117 factors
118 }
119
120 fn assert_in_range(&self, n: usize) {
121 assert!(
122 n <= self.limit(),
123 "n exceeds the precomputed range: n = {n}, limit = {}",
124 self.limit(),
125 );
126 }
127}
128
129#[cfg(test)]
130mod tests {
131 use super::Sieve;
132
133 #[test]
134 fn identifies_primes() {
135 let sieve = Sieve::new(20);
136
137 assert!(!sieve.is_prime(0));
138 assert!(!sieve.is_prime(1));
139 assert!(sieve.is_prime(2));
140 assert!(sieve.is_prime(19));
141 assert!(!sieve.is_prime(20));
142
143 assert_eq!(
144 sieve.primes().collect::<Vec<_>>(),
145 vec![2, 3, 5, 7, 11, 13, 17, 19],
146 );
147 }
148
149 #[test]
150 fn factorizes_numbers() {
151 let sieve = Sieve::new(100);
152
153 assert_eq!(sieve.prime_factorize(1), vec![]);
154 assert_eq!(sieve.prime_factorize(2), vec![(2, 1)]);
155
156 assert_eq!(sieve.prime_factorize(84), vec![(2, 2), (3, 1), (7, 1)],);
157
158 assert_eq!(sieve.prime_factorize(97), vec![(97, 1)],);
159 }
160}