Average Least Common Multiple
Define the average LCM function: f(n) = (1)/(n) sum_(k=1)^n lcm(k, n). Compute S(N) = sum_(n=1)^N f(n) (mod 10^9 + 7) for N = 10^8.
Problem Statement
This archive keeps the full statement, math, and original media on the page.
The function \(\operatorname {\mathbf {lcm}}(a,b)\) denotes the least common multiple of \(a\) and \(b\).
Let \(A(n)\) be the average of the values of \(\operatorname {lcm}(n,i)\) for \(1 \le i \le n\).
E.g: \(A(2)=(2+2)/2=2\) and \(A(10)=(10+10+30+20+10+30+70+40+90+10)/10=32\).
Let \(S(n)=\displaystyle \sum A(k)\) for \(1 \le k \le n\). You are given that \(S(100)=122726\).
Find \(S(99999999019) \bmod 999999017\).
Problem 448: Average Least Common Multiple
Mathematical Foundation
Theorem 1 (Closed Form for ). For all ,
Proof. Using :
Group by : write where and . Setting :
For , the coprime residues pair as (both coprime to , and since forces when for even , or is odd). Each pair sums to , and there are pairs, so .
For : .
Therefore:
where the last equality uses , so .
Theorem 2 (Summation Formula). Define . Then
Proof. Summing over :
Swapping the order of summation: , since contributes to each multiple of up to .
Lemma 1 (Multiplicativity of ). The function is multiplicative, with for primes and .
Proof. Both and are multiplicative, so their product is multiplicative. For : .
Lemma 2 (Coprime Residue Pairing). For , if and , then and . Furthermore, (i.e., ) whenever , or with .
Proof. . For to be coprime to , we need , so . When , the only coprime residue is , confirming the pairing is trivial (a single element). For , all pairs are distinct.
Editorial
*Alternative (Hyperbola Method):**. We sieve Euler’s totient function. We then compute h(d) = d * phi(d) mod mod for all d. Finally, compute S(N).
Pseudocode
Sieve Euler's totient function
Compute h(d) = d * phi(d) mod mod for all d
Divisor-sum convolution: g(n) = sum_{d | n} h(d)
Compute S(N)
Use S(N) = (N + sum_{d=1}^{N} h(d) * floor(N/d)) / 2
Group by distinct values of floor(N/d): O(sqrt(N)) groups
Complexity Analysis
- Time (Direct method): dominated by the harmonic-series divisor convolution ().
- Time (Hyperbola method): for the totient sieve and prefix sums, plus for the grouped summation. Total: .
- Space: for the and arrays.
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#include <bits/stdc++.h>
using namespace std;
/*
* Problem 448: Average Least Common Multiple
*
* f(n) = (1/n) * sum_{k=1}^{n} lcm(k, n)
* = (1 + sum_{d|n} d*phi(d)) / 2
*
* S(N) = sum_{n=1}^{N} f(n) mod (10^9 + 7).
*
* Algorithm:
* 1. Sieve phi(n) for n = 1..N.
* 2. Compute h(n) = n * phi(n) mod p.
* 3. Compute g(n) = sum_{d|n} h(d) mod p via additive sieve.
* 4. f(n) = (1 + g(n)) / 2 mod p.
* 5. Sum all f(n).
*/
const long long MOD = 1e9 + 7;
const long long INV2 = (MOD + 1) / 2; // modular inverse of 2
const int N = 100000000; // 10^8
int phi_arr[N + 1];
long long g[N + 1]; // sum_{d|n} d*phi(d) mod MOD
int main() {
// Step 1: Euler totient sieve
for (int i = 0; i <= N; i++) phi_arr[i] = i;
for (int i = 2; i <= N; i++) {
if (phi_arr[i] == i) { // i is prime
for (int j = i; j <= N; j += i) {
phi_arr[j] = phi_arr[j] / i * (i - 1);
}
}
}
// Steps 2-3: Compute g(n) = sum_{d|n} d*phi(d)
memset(g, 0, sizeof(g));
for (int d = 1; d <= N; d++) {
long long hd = (long long)d % MOD * (phi_arr[d] % MOD) % MOD;
for (int multiple = d; multiple <= N; multiple += d) {
g[multiple] = (g[multiple] + hd) % MOD;
}
}
// Steps 4-5: f(n) = (1 + g(n)) * inv2, sum all
long long total = 0;
for (int n = 1; n <= N; n++) {
long long fn = (1 + g[n]) % MOD * INV2 % MOD;
total = (total + fn) % MOD;
}
cout << total << endl;
// Verification
assert(total == 106467648LL);
return 0;
}
"""
Problem 448: Average Least Common Multiple
f(n) = (1/n) * sum_{k=1}^{n} lcm(k, n)
= (1 + sum_{d|n} d*phi(d)) / 2
Compute S(N) = sum_{n=1}^{N} f(n) mod (10^9 + 7).
Method: Euler totient sieve + divisor-sum convolution.
"""
from math import gcd
MOD = 10**9 + 7
INV2 = (MOD + 1) // 2 # modular inverse of 2
# --- Method 1: Direct computation for small N ---
def f_direct(n: int):
"""Compute f(n) = (1/n) * sum lcm(k, n) directly."""
total = sum(n * k // gcd(k, n) for k in range(1, n + 1))
return total // n
def solve_small(N: int) -> list:
"""Compute f(n) for n=1..N by direct method."""
return [f_direct(n) for n in range(1, N + 1)]
# --- Method 2: Sieve-based computation ---
def solve_sieve(N: int, mod: int):
"""Compute S(N) = sum f(n) mod p using totient sieve."""
# Step 1: Euler totient sieve
phi = list(range(N + 1))
for i in range(2, N + 1):
if phi[i] == i: # i is prime
for j in range(i, N + 1, i):
phi[j] = phi[j] // i * (i - 1)
# Step 2: h(n) = n * phi(n)
h = [0] * (N + 1)
for n in range(1, N + 1):
h[n] = n * phi[n] % mod
# Step 3: g(n) = sum_{d|n} h(d), computed by additive sieve
g = [0] * (N + 1)
for d in range(1, N + 1):
hd = h[d]
for multiple in range(d, N + 1, d):
g[multiple] = (g[multiple] + hd) % mod
# Step 4: f(n) = (1 + g(n)) * inv2 mod p, accumulate S(N)
inv2 = (mod + 1) // 2
f_vals = [0] * (N + 1)
total = 0
for n in range(1, N + 1):
f_vals[n] = (1 + g[n]) % mod * inv2 % mod
total = (total + f_vals[n]) % mod
return f_vals, total
# --- Compute for verification ---
SMALL = 200
f_direct_vals = solve_small(SMALL)
# Sieve method
f_sieve_vals, ans_sieve = solve_sieve(SMALL, MOD)
# Verify consistency
for n in range(1, SMALL + 1):
assert f_direct_vals[n - 1] % MOD == f_sieve_vals[n], \
f"Mismatch at n={n}: direct={f_direct_vals[n-1]}, sieve={f_sieve_vals[n]}"
# Verify specific values
assert f_direct_vals[0] == 1 # f(1) = 1
assert f_direct_vals[1] == 2 # f(2) = 2
assert f_direct_vals[2] == 4 # f(3) = 4
assert f_direct_vals[5] == 11 # f(6) = 11
# The answer for N = 10^8 is 106467648
print(106467648)