Original post: https://math.stackexchange.com/questions/316376/how-to-calculate-these-totient-summation-sums-efficiently
Background:
- Totient summatory function: Wolfram
Python code snippet:
class TotientSummatoryFunction():
"""Totient summatory function class."""
def __init__(self, bound, mod):
"""Initialize.
Args:
bound: An integer.
mod: An integer.
"""
self.mod = mod
self.small_values = None
self.small_value_bound = None
self.big_values = {}
self.InitSmallValues(bound)
def InitSmallValues(self, bound):
"""Initialize small values for totient summatory function.
Args:
bound: An integer.
"""
n = 3 * int(math.pow(bound, 2 / 3))
assert(n**3 >= bound**2)
print('InitSmallValues({n})'.format(n=n))
phi = [i for i in range(n + 1)]
for i in range(2, n + 1):
if phi[i] != i:
continue
for j in range(i, n + 1, i):
phi[j] = phi[j] // i * (i - 1)
self.small_values = [0 for i in range(n + 1)]
self.small_values[1] = phi[1] % self.mod
for i in range(2, n + 1):
self.small_values[i] = (self.small_values[i - 1] + phi[i]) % self.mod
self.small_value_bound = n
def Get(self, n):
"""Get totient summatory function value.
Args:
n: An integer.
Returns:
An integer.
"""
if n <= self.small_value_bound:
return self.small_values[n]
if n not in self.big_values:
result = n * (n + 1) // 2
m = self.IntegerSqrt(n)
for d in range(1, m + 1):
result -= self.Get(d) * (n // d - n // (d + 1))
for k in range(2, n // (m + 1) + 1):
result -= self.Get(n // k)
self.big_values[n] = result % self.mod
return self.big_values[n]
def IntegerSqrt(self, n):
"""
Get the integer part of Sqrt[n].
Args:
n: An integer.
Returns:
An integer.
"""
guess = (n >> n.bit_length() // 2) + 1
result = (guess + n // guess) // 2
while abs(result - guess) > 1:
guess = result
result = (guess + n // guess) // 2
while result * result > n:
result -= 1
return result
沒有留言:
張貼留言