-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmoebius_transform_fast.sf
More file actions
41 lines (30 loc) · 887 Bytes
/
moebius_transform_fast.sf
File metadata and controls
41 lines (30 loc) · 887 Bytes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#!/usr/bin/ruby
# Decently efficient implementations of the Möbius inversion formula.
# Formula definition:
# g(n) = Sum_{d|n} mu(d) * f(n/d)
# f(n) = Sum_{d|n} g(d)
# See also:
# https://en.wikipedia.org/wiki/M%C3%B6bius_inversion_formula
func moebius_transform(n, f) {
var a = n.factor_prod {|p,e| ipow(p, e-1) }
var b = idiv(n, a)
b.divisors.sum {|d|
moebius(idiv(b, d)) * f(a * d)
}
}
func moebius_transform_alt(n, f) {
n.squarefree_divisors.sum {|d|
moebius(d) * f(idiv(n, d))
}
}
var f = { .phi }
say 30.of {|n| moebius_transform(n, f) } # OEIS: A007431
say 30.of {|n| moebius_transform_alt(n, f) } # OEIS: A007431
assert_eq(
30.of {|n| f(n) },
30.of {|n| n.divisors.sum{|d| moebius_transform(d,f) } }
)
assert_eq(
30.of {|n| f(n) },
30.of {|n| n.divisors.sum{|d| moebius_transform_alt(d,f) } }
)