1pub fn totient(mut n: u64) -> u64 {
8 let mut ret = n;
9
10 let mut i = 2;
11 while i * i <= n {
12 if n % i == 0 {
13 ret -= ret / i;
14 while n % i == 0 {
15 n /= i;
16 }
17 }
18
19 i += 1;
20 }
21
22 if n != 1 {
23 ret -= ret / n;
24 }
25
26 ret
27}
28
29pub fn totient_table(n: usize) -> Vec<u64> {
33 let mut ret = (0..=n as u64).collect::<Vec<_>>();
34
35 for i in 2..=n {
36 if ret[i] == i as u64 {
37 for j in (i..=n).step_by(i) {
38 ret[j] = ret[j] / (i as u64) * (i as u64 - 1);
39 }
40 }
41 }
42
43 ret
44}
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49
50 #[test]
51 fn test() {
52 assert_eq!(
54 &totient_table(69)[1..],
55 vec![
56 1, 1, 2, 2, 4, 2, 6, 4, 6, 4, 10, 4, 12, 6, 8, 8, 16, 6, 18, 8, 12, 10, 22, 8, 20,
57 12, 18, 12, 28, 8, 30, 16, 20, 16, 24, 12, 36, 18, 24, 16, 40, 12, 42, 20, 24, 22,
58 46, 16, 42, 20, 32, 24, 52, 18, 40, 24, 36, 28, 58, 16, 60, 30, 36, 32, 48, 20, 66,
59 32, 44
60 ]
61 .as_slice()
62 );
63 }
64}