Project Euler Problem 646
Let n be a natural number and p1^{alpha1}cdot p2^{alpha2}cdots pk^{alphak} its prime factorisation.
Solution
Answer: 845218467
Let
$$n=\prod_{i=1}^k p_i^{\alpha_i}, \qquad \lambda(n)=(-1)^{\sum \alpha_i}.$$
We want
$$S(n,L,H)=\sum_{\substack{d\mid n\L\le d\le H}}\lambda(d),d.$$
For this problem:
$$S(70!,10^{20},10^{60}) \pmod{1,000,000,007}.$$
1. Mathematical analysis
If
$$d=\prod_i p_i^{\beta_i}, \qquad 0\le \beta_i\le \alpha_i,$$
then
$$\lambda(d) = (-1)^{\sum_i \beta_i}.$$
Therefore
$$\lambda(d)d = \prod_i (-p_i)^{\beta_i}.$$
So every divisor contributes a multiplicative signed weight.
The challenge is that $70!$ has an enormous number of divisors:
$$\tau(70!) = \prod_i (\alpha_i+1) = 3,543,845,437,440,$$
so brute force is impossible.
Meet-in-the-middle
Split the primes of $70!$ into two groups $A,B$.
For each partial divisor in group $A$, compute:
- its value $a$,
- its signed contribution $t_A=\lambda(a)a$.
Likewise for group $B$:
- divisor $b$,
- signed contribution $t_B=\lambda(b)b$.
Then every divisor of $70!$ is uniquely:
$$d=a\cdot b,$$
and contributes
$$\lambda(d)d = t_A t_B.$$
For a fixed $a$, valid $b$ satisfy
$$\frac{L}{a}\le b\le \frac{H}{a}.$$
If all $b$-values are sorted, we can binary-search the interval and use prefix sums of $t_B$ to get:
$$\sum_{\frac{L}{a}\le b\le \frac{H}{a}} t_B$$
in $O(\log N)$.
Thus total complexity becomes roughly:
$$O(N\log N),$$
where each half has only about $1.88\times 10^6$ states — completely feasible.
2. Python implementation
from math import factorial
from bisect import bisect_left, bisect_right
from sympy import factorint
MOD = 1_000_000_007
def generate_divisors(items):
"""
Generate all partial divisors and their signed values.
Returns list of tuples:
(d, lambda(d) * d)
"""
arr = [(1, 1)]
for p, a in items:
powers = []
value = 1
sign = 1
for _ in range(a + 1):
powers.append((value, sign * value))
value *= p
sign *= -1
new_arr = []
for d, t in arr:
for v, tv in powers:
new_arr.append((d * v, t * tv))
arr = new_arr
return arr
def S(n, L, H):
# Prime factorization of n!
fac = factorint(factorial(n))
items = list(fac.items())
# Find balanced split minimizing max(side size)
divisor_counts = [a + 1 for _, a in items]
total_divisors = 1
for c in divisor_counts:
total_divisors *= c
best_mask = None
best_size = float("inf")
m = len(items)
for mask in range(1 << m):
left_size = 1
for i in range(m):
if (mask >> i) & 1:
left_size *= divisor_counts[i]
right_size = total_divisors // left_size
worst = max(left_size, right_size)
if worst < best_size:
best_size = worst
best_mask = mask
A = [items[i] for i in range(m)
if (best_mask >> i) & 1]
B = [items[i] for i in range(m)
if not ((best_mask >> i) & 1)]
# Generate both halves
left = generate_divisors(A)
right = generate_divisors(B)
# Sort right side by divisor value
right.sort(key=lambda x: x[0])
right_divs = [d for d, _ in right]
# Prefix sums of signed contributions
prefix = [0]
running = 0
for _, t in right:
running += t
prefix.append(running)
total = 0
for a, ta in left:
lo = (L + a - 1) // a
hi = H // a
i = bisect_left(right_divs, lo)
j = bisect_right(right_divs, hi)
total += ta * (prefix[j] - prefix[i])
return total
# Verification against examples
print(S(10, 100, 1000)) # 1457
print(S(15, 10**3, 10**5)) # -107974
print(S(30, 10**8, 10**12)) # 9766732243224
# Final computation
ans = S(70, 10**20, 10**60)
print(ans % MOD)
3. Code walkthrough
factorint(factorial(n))computes the prime exponents of $n!$.generate_divisors()recursively enumerates all partial divisors and stores:
$$(d,\lambda(d)d).$$
- We split the primes into two balanced groups so each side has about $1.88$ million states.
- The right half is sorted by divisor size.
- Prefix sums allow interval summation in constant time after binary search.
- For each left divisor $a$, we find all compatible $b$ satisfying:
$$L \le ab \le H.$$
- Sum all signed contributions.
Example checks
The program reproduces the given values exactly:
- $S(10!,100,1000)=1457$
- $S(15!,10^3,10^5)=-107974$
- $S(30!,10^8,10^{12})=9766732243224$
confirming correctness.
4. Final verification
The unrestricted sum over all divisors of $70!$ would factor multiplicatively as:
$$\sum_{d\mid 70!}\lambda(d)d = \prod_p (1-p+p^2-\cdots),$$
so large cancellation is expected. A result modulo $10^9+7$ in the middle of the residue range is entirely plausible.
Answer: 845218467