haar_lib/math/
multiplicative.rs1use std::ops::Mul;
4
5use crate::num::one_zero::One;
6
7pub fn multiplicative_table<T, F>(n: usize, f: F) -> Vec<T>
11where
12 T: Copy + Default + Mul<Output = T> + One,
13 F: Fn(u64, u32) -> T,
14{
15 let mut ret = vec![T::default(); n + 1];
16 let mut p = vec![(0, 0, 0); n + 1];
17
18 ret[1] = T::one();
19
20 for i in 2..=n {
21 if p[i] == (0, 0, 0) {
22 for j in (i..=n).step_by(i) {
23 if p[j] == (0, 0, 0) {
24 let mut k = 0;
25 let mut m = j;
26
27 while m % i == 0 {
28 m /= i;
29 k += 1;
30 }
31
32 p[j] = (m, i, k);
33 }
34 }
35 }
36 }
37
38 for i in 2..=n {
39 let (m, j, k) = p[i];
40 ret[i] = ret[m] * f(j as u64, k);
41 }
42
43 ret
44}
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49 use crate::{math::totient::totient_table, timer};
50
51 #[test]
52 fn totient() {
53 let f = |p: u64, k: u32| p.pow(k) - p.pow(k - 1);
54
55 for n in [1, 10, 100, 1000, 10000, 100000, 1000000] {
56 let res = timer! {n, {
57 multiplicative_table(n, f)
58 }};
59
60 let ans = totient_table(n);
61
62 assert_eq!(res, ans);
63 }
64 }
65
66 #[test]
67 fn mobius() {
68 let f = |p: u64, k: u32| if k == 1 { -1 } else { 0 };
69
70 for n in [1, 10, 100, 1000, 10000, 100000, 1000000] {
71 let _res = timer! {n, {
72 multiplicative_table(n, f)
73 }};
74 }
75 }
76}