cp_library_rs/number_theory/factorize_query.rs
1//! ## 前計算ありの素因数分解
2//!
3//! $`N`$ までの数の素因数分解を
4//! - 前計算: $`O(N \log\log N)`$ 時間
5//! - クエリ: $`O(\log N)`$ 時間
6//!
7//! で行う。
8
9/// 前計算ありの素因数分解
10pub struct FactorTable {
11 pub n: usize,
12 pub sieve: Vec<usize>,
13}
14
15impl FactorTable {
16 /// 前計算を行う
17 /// - $`O(N \log\log N)`$ 時間で篩を作成
18 pub fn new(n: usize) -> Self {
19 let mut sieve = vec![0; n + 1];
20 if n >= 1 {
21 sieve[1] = 1;
22 }
23 for i in 2..=n {
24 if sieve[i] == 0 {
25 // i は素数
26 sieve[i] = i;
27 // i*i から始める(溢れ注意)
28 if i <= n / i {
29 let mut j = i * i;
30 while j <= n {
31 if sieve[j] == 0 {
32 sieve[j] = i;
33 }
34 j += i;
35 }
36 }
37 }
38 }
39 Self { n, sieve }
40 }
41
42 /// 素因数分解を行い,素因数のベクタを返す
43 ///
44 /// **戻り値**
45 /// - 素因数のリスト
46 ///
47 /// - 時間計算量: $`O(\log x)`$
48 pub fn factorize(&self, mut x: usize) -> Vec<usize> {
49 assert!(1 <= x && x <= self.n);
50 let mut factors = vec![];
51 while x > 1 {
52 let p = self.sieve[x];
53 factors.push(p);
54 x /= p;
55 }
56 factors
57 }
58
59 /// 素因数分解を行い,(素因数, 指数) のベクタを返す
60 ///
61 /// **戻り値**
62 /// - (素因数, 指数) のベクタ
63 ///
64 /// - 時間計算量: $`O(\log x)`$
65 pub fn factorize_pairs(&self, mut x: usize) -> Vec<(usize, usize)> {
66 assert!(1 <= x && x <= self.n);
67 let mut pairs: Vec<(usize, usize)> = vec![];
68 while x > 1 {
69 let p = self.sieve[x];
70 let mut e = 0;
71 while x % p == 0 {
72 x /= p;
73 e += 1;
74 }
75 pairs.push((p, e));
76 }
77 pairs
78 }
79}