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