Divisor Functions — Practice Tasks¶
All tasks must be solved in Go, Java, and Python. Each task ships with a precise spec and starter code in all three languages. Implement the divisor logic and validate against the evaluation criteria. Always validate against the closed-form formulas or a brute-force divisor walk on small inputs before trusting your sieve. Use 64-bit for σ everywhere.
Beginner Tasks (5)¶
Task 1 — d(n) and σ(n) for a single number¶
Problem. Implement dSigma(n) returning the number of divisors d(n) and the sum of divisors σ(n), computed by factorizing n with trial division. Do not list all divisors.
Input / Output spec. - Input: one integer n. - Output: two integers d(n) and σ(n) on one line, space-separated.
Constraints. 1 ≤ n ≤ 10^{12}.
Hint. For each prime factor p with exponent a, multiply d by (a+1) and σ by (1 + p + … + p^a) (accumulate the geometric sum with integer addition). Do not forget the leftover prime when the trial loop ends with n > 1.
Starter — Go.
package main
import "fmt"
func dSigma(n int64) (int64, int64) {
// TODO: trial-division factorization; build d and sigma
return 0, 0
}
func main() {
var n int64
fmt.Scan(&n)
d, s := dSigma(n)
fmt.Println(d, s)
}
Starter — Java.
import java.util.*;
public class Task1 {
static long[] dSigma(long n) {
// TODO
return new long[]{0, 0};
}
public static void main(String[] args) {
long n = new Scanner(System.in).nextLong();
long[] r = dSigma(n);
System.out.println(r[0] + " " + r[1]);
}
}
Starter — Python.
def d_sigma(n):
# TODO: trial-division factorization
return 0, 0
if __name__ == "__main__":
d, s = d_sigma(int(input()))
print(d, s)
Evaluation. dSigma(12) = (6, 28); dSigma(360) = (24, 1170); dSigma(97) = (2, 98); dSigma(1) = (1, 1).
Task 2 — Naive divisor walk (√n pairing)¶
Problem. Implement dSigma(n) without factorization, by walking i from 1 to √n and using divisor pairs (i, n/i). Count the square root only once for perfect squares.
Input / Output spec. Input n; output d(n) and σ(n).
Constraints. 1 ≤ n ≤ 10^{12}.
Hint. When i*i == n, add i once. Otherwise add both i and n/i.
Starter — Go.
package main
import "fmt"
func dSigma(n int64) (int64, int64) {
// TODO: loop i while i*i <= n
return 0, 0
}
func main() {
var n int64
fmt.Scan(&n)
d, s := dSigma(n)
fmt.Println(d, s)
}
Starter — Java.
import java.util.*;
public class Task2 {
static long[] dSigma(long n) { /* TODO */ return new long[]{0, 0}; }
public static void main(String[] args) {
long n = new Scanner(System.in).nextLong();
long[] r = dSigma(n);
System.out.println(r[0] + " " + r[1]);
}
}
Starter — Python.
def d_sigma(n):
# TODO: i*i <= n pairing
return 0, 0
if __name__ == "__main__":
d, s = d_sigma(int(input()))
print(d, s)
Evaluation. Must match Task 1 for n = 12, 36, 360, 49. Note 36 is a perfect square: d(36)=9, σ(36)=91.
Task 3 — Divisor sieve for all m ≤ N¶
Problem. Build d[m] and σ[m] for all m ≤ N with the O(N log N) divisor sieve, then answer q queries returning d(x) and σ(x).
Input / Output spec. Input N, q, then q values x (1 ≤ x ≤ N). For each, output d(x) and σ(x).
Constraints. 1 ≤ N ≤ 10^6, 1 ≤ q ≤ 10^5.
Hint. For each divisor div from 1 to N, iterate multiples m = div, 2div, … and do cnt[m]++, sum[m] += div. Use 64-bit for σ.
Starter — Go.
package main
import "fmt"
func sieve(N int) ([]int, []int64) {
// TODO
return nil, nil
}
func main() {
var N, q int
fmt.Scan(&N, &q)
d, s := sieve(N)
for ; q > 0; q-- {
var x int
fmt.Scan(&x)
fmt.Println(d[x], s[x])
}
}
Starter — Java.
import java.util.*;
public class Task3 {
static int[] d;
static long[] s;
static void sieve(int N) { /* TODO */ }
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt(), q = sc.nextInt();
sieve(N);
StringBuilder sb = new StringBuilder();
while (q-- > 0) { int x = sc.nextInt(); sb.append(d[x]).append(' ').append(s[x]).append('\n'); }
System.out.print(sb);
}
}
Starter — Python.
import sys
def sieve(N):
# TODO
return [], []
def main():
data = sys.stdin.read().split()
i = 0
N, q = int(data[i]), int(data[i + 1]); i += 2
d, s = sieve(N)
out = []
for _ in range(q):
x = int(data[i]); i += 1
out.append(f"{d[x]} {s[x]}")
print("\n".join(out))
main()
Evaluation. Queries 6, 12, 360 return (4,12), (6,28), (24,1170).
Task 4 — Classify perfect / abundant / deficient¶
Problem. For each query x ≤ N, print whether x is perfect, abundant, or deficient, using a sieved σ array.
Input / Output spec. Input N, q, then q values x. Output one classification per query.
Constraints. 1 ≤ N ≤ 10^6, 1 ≤ q ≤ 10^5.
Hint. Let s = σ(x) − x. Perfect if s == x, abundant if s > x, else deficient.
Starter — Go.
package main
import "fmt"
func sigmaSieve(N int) []int64 {
// TODO
return nil
}
func main() {
var N, q int
fmt.Scan(&N, &q)
sig := sigmaSieve(N)
for ; q > 0; q-- {
var x int
fmt.Scan(&x)
s := sig[x] - int64(x)
switch {
case s == int64(x):
fmt.Println("perfect")
case s > int64(x):
fmt.Println("abundant")
default:
fmt.Println("deficient")
}
}
}
Starter — Java.
import java.util.*;
public class Task4 {
static long[] sigmaSieve(int N) { /* TODO */ return new long[N + 1]; }
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt(), q = sc.nextInt();
long[] sig = sigmaSieve(N);
StringBuilder sb = new StringBuilder();
while (q-- > 0) {
int x = sc.nextInt();
long s = sig[x] - x;
sb.append(s == x ? "perfect" : (s > x ? "abundant" : "deficient")).append('\n');
}
System.out.print(sb);
}
}
Starter — Python.
import sys
def sigma_sieve(N):
# TODO
return [0] * (N + 1)
def main():
d = sys.stdin.read().split()
i = 0
N, q = int(d[0]), int(d[1]); i = 2
sig = sigma_sieve(N)
out = []
for _ in range(q):
x = int(d[i]); i += 1
s = sig[x] - x
out.append("perfect" if s == x else ("abundant" if s > x else "deficient"))
print("\n".join(out))
main()
Evaluation. 6 → perfect, 12 → abundant, 16 → deficient, 28 → perfect.
Task 5 — Sum of divisors over a range (prefix sums)¶
Problem. Sieve σ, build a prefix-sum array, then answer q queries "sum of σ(i) for i ∈ [a, b]" each in O(1).
Input / Output spec. Input N, q, then q pairs a b. Output the sum per query (64-bit; may need bigger for very large ranges, but stay within 64-bit for these constraints).
Constraints. 1 ≤ N ≤ 2·10^6, 1 ≤ q ≤ 10^5, 1 ≤ a ≤ b ≤ N.
Hint. pref[i] = pref[i-1] + σ(i); answer = pref[b] − pref[a-1].
Starter — Go.
package main
import "fmt"
func main() {
var N, q int
fmt.Scan(&N, &q)
// TODO: sieve sigma, build pref []int64
for ; q > 0; q-- {
var a, b int
fmt.Scan(&a, &b)
// TODO: print pref[b] - pref[a-1]
}
}
Starter — Java.
import java.util.*;
public class Task5 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt(), q = sc.nextInt();
// TODO: sieve sigma into long[], build long[] pref
StringBuilder sb = new StringBuilder();
while (q-- > 0) {
int a = sc.nextInt(), b = sc.nextInt();
// TODO: sb.append(pref[b] - pref[a-1]).append('\n');
}
System.out.print(sb);
}
}
Starter — Python.
import sys
def main():
d = iter(sys.stdin.read().split())
N, q = int(next(d)), int(next(d))
# TODO: sieve sigma, build prefix sums
out = []
for _ in range(q):
a, b = int(next(d)), int(next(d))
# TODO: out.append(str(pref[b] - pref[a-1]))
print("\n".join(out))
main()
Evaluation. Sum of σ over [1,10] is 1+3+4+7+6+12+8+15+13+18 = 87; over [1,1] is 1; over [6,6] is 12.
Intermediate Tasks (5)¶
Task 6 — Linear sieve for d and σ (O(N))¶
Problem. Compute d[m] and σ[m] for all m ≤ N using the linear sieve with exponent tracking (true O(N)), then answer q queries.
Input / Output spec. Input N, q, then q values x. Output d(x) and σ(x).
Constraints. 1 ≤ N ≤ 5·10^6, 1 ≤ q ≤ 10^5.
Hint. Track cnt[n] (exponent of smallest prime) and spp[n] = σ(p^{cnt}). Coprime case: d=2·d[i], σ=(p+1)·σ[i]. Exponent-raise case: d = d[i]/(cnt+1)*(cnt+2), spp = p·spp[i]+1, σ = σ[i]/spp[i]*spp.
Starter — Go.
package main
import "fmt"
func linearDSigma(N int) ([]int, []int64) {
// TODO: linear sieve with cnt[] and spp[]
return nil, nil
}
func main() {
var N, q int
fmt.Scan(&N, &q)
d, s := linearDSigma(N)
for ; q > 0; q-- {
var x int
fmt.Scan(&x)
fmt.Println(d[x], s[x])
}
}
Starter — Java.
import java.util.*;
public class Task6 {
static int[] d;
static long[] s;
static void linearDSigma(int N) { /* TODO */ }
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt(), q = sc.nextInt();
linearDSigma(N);
StringBuilder sb = new StringBuilder();
while (q-- > 0) { int x = sc.nextInt(); sb.append(d[x]).append(' ').append(s[x]).append('\n'); }
System.out.print(sb);
}
}
Starter — Python.
def linear_d_sigma(N):
# TODO: linear sieve, O(N)
return [], []
if __name__ == "__main__":
import sys
it = iter(sys.stdin.read().split())
N, q = int(next(it)), int(next(it))
d, s = linear_d_sigma(N)
print("\n".join(f"{d[int(next(it))]} {s[x]}" if False else "" for _ in range(0))) # replace
# Correct loop:
out = []
for _ in range(q):
x = int(next(it))
out.append(f"{d[x]} {s[x]}")
print("\n".join(out))
Evaluation. Must match the O(N log N) divisor sieve for all n ≤ N (cross-check). d(720)=30, σ(720)=2418.
Task 7 — Amicable pairs up to N¶
Problem. Find all amicable pairs (a, b) with a < b ≤ N: distinct numbers where s(a) = b and s(b) = a (with s(x) = σ(x) − x).
Input / Output spec. Input N; output each pair a b on its own line, sorted by a.
Constraints. 1 ≤ N ≤ 10^6.
Hint. Sieve σ, compute s[x] = σ(x) − x. For each a, let b = s[a]; report if b ≤ N, b != a, s[b] == a, and a < b.
Starter — Go.
package main
import "fmt"
func sigmaSieve(N int) []int64 { /* TODO */ return nil }
func main() {
var N int
fmt.Scan(&N)
sig := sigmaSieve(N)
s := make([]int64, N+1)
for i := 1; i <= N; i++ {
s[i] = sig[i] - int64(i)
}
// TODO: for each a, check b = s[a]
}
Starter — Java.
import java.util.*;
public class Task7 {
static long[] sigmaSieve(int N) { /* TODO */ return new long[N + 1]; }
public static void main(String[] args) {
int N = new Scanner(System.in).nextInt();
long[] sig = sigmaSieve(N);
long[] s = new long[N + 1];
for (int i = 1; i <= N; i++) s[i] = sig[i] - i;
// TODO: report amicable pairs a < b
}
}
Starter — Python.
def sigma_sieve(N):
# TODO
return [0] * (N + 1)
if __name__ == "__main__":
N = int(input())
sig = sigma_sieve(N)
s = [sig[i] - i for i in range(N + 1)]
# TODO: for a in range(2, N+1): b = s[a]; check conditions
Evaluation. For N = 1500, output is 220 284 and 1184 1210.
Task 8 — Highly composite numbers up to N¶
Problem. Output every n ≤ N that has strictly more divisors than all smaller positive integers, together with its divisor count.
Input / Output spec. Input N; output each n d(n) on its own line, in increasing n.
Constraints. 1 ≤ N ≤ 10^6.
Hint. Sieve d, scan n from 1 to N, keep a running max; emit n whenever d[n] beats the previous max.
Starter — Go.
package main
import "fmt"
func dSieve(N int) []int { /* TODO */ return nil }
func main() {
var N int
fmt.Scan(&N)
d := dSieve(N)
best := 0
for n := 1; n <= N; n++ {
if d[n] > best {
best = d[n]
fmt.Println(n, d[n])
}
}
}
Starter — Java.
import java.util.*;
public class Task8 {
static int[] dSieve(int N) { /* TODO */ return new int[N + 1]; }
public static void main(String[] args) {
int N = new Scanner(System.in).nextInt();
int[] d = dSieve(N);
int best = 0;
for (int n = 1; n <= N; n++) if (d[n] > best) { best = d[n]; System.out.println(n + " " + d[n]); }
}
}
Starter — Python.
def d_sieve(N):
# TODO
return [0] * (N + 1)
if __name__ == "__main__":
N = int(input())
d = d_sieve(N)
best = 0
for n in range(1, N + 1):
if d[n] > best:
best = d[n]
print(n, d[n])
Evaluation. For N = 60: 1 1, 2 2, 4 3, 6 4, 12 6, 24 8, 36 9, 48 10, 60 12.
Task 9 — σ_k sieve¶
Problem. Given k, compute σ_k(m) = Σ_{d∣m} d^k for all m ≤ N, answer q queries. Output modulo 1_000_000_007.
Input / Output spec. Input N, k, q, then q values x. Output σ_k(x) mod 1e9+7.
Constraints. 1 ≤ N ≤ 10^6, 0 ≤ k ≤ 5, 1 ≤ q ≤ 10^5.
Hint. Divisor sieve: sum[m] = (sum[m] + pow(d, k)) % MOD. Precompute pow(d,k) per d. σ₀ = d, σ₁ = σ.
Starter — Go.
package main
import "fmt"
const MOD = 1_000_000_007
func sigmaK(N, k int) []int64 {
// TODO: divisor sieve accumulating d^k mod MOD
return nil
}
func main() {
var N, k, q int
fmt.Scan(&N, &k, &q)
sk := sigmaK(N, k)
for ; q > 0; q-- {
var x int
fmt.Scan(&x)
fmt.Println(sk[x])
}
}
Starter — Java.
import java.util.*;
public class Task9 {
static final long MOD = 1_000_000_007L;
static long[] sigmaK(int N, int k) { /* TODO */ return new long[N + 1]; }
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt(), k = sc.nextInt(), q = sc.nextInt();
long[] sk = sigmaK(N, k);
StringBuilder sb = new StringBuilder();
while (q-- > 0) sb.append(sk[sc.nextInt()]).append('\n');
System.out.print(sb);
}
}
Starter — Python.
MOD = 1_000_000_007
def sigma_k(N, k):
# TODO: divisor sieve with d**k % MOD
return [0] * (N + 1)
if __name__ == "__main__":
import sys
it = iter(sys.stdin.read().split())
N, k, q = int(next(it)), int(next(it)), int(next(it))
sk = sigma_k(N, k)
print("\n".join(str(sk[int(next(it))]) for _ in range(q)))
Evaluation. σ₀(6)=4, σ₁(6)=12, σ₂(6)=1+4+9+36=50, σ₂(10)=1+4+25+100=130.
Task 10 — Triangular number with over 500 divisors (Project Euler 12)¶
Problem. Find the first triangular number T_n = n(n+1)/2 with more than 500 divisors. Use that gcd(n, n+1)=1, so d(T_n) factors via d of the two coprime halves.
Input / Output spec. Input a threshold t; output the first triangular number with > t divisors.
Constraints. 1 ≤ t ≤ 1000.
Hint. T_n = n(n+1)/2. If n is even, T_n = (n/2)·(n+1) with coprime factors; else T_n = n·((n+1)/2). Then d(T_n) = d(a)·d(b) for the coprime split. Compute d of each factor by trial division.
Starter — Go.
package main
import "fmt"
func dOf(n int64) int64 {
// TODO: number of divisors via trial division
return 0
}
func main() {
var t int64
fmt.Scan(&t)
for n := int64(1); ; n++ {
var a, b int64
if n%2 == 0 {
a, b = n/2, n+1
} else {
a, b = n, (n+1)/2
}
if dOf(a)*dOf(b) > t {
fmt.Println(a * b)
return
}
}
}
Starter — Java.
import java.util.*;
public class Task10 {
static long dOf(long n) { /* TODO */ return 0; }
public static void main(String[] args) {
long t = new Scanner(System.in).nextLong();
for (long n = 1; ; n++) {
long a = (n % 2 == 0) ? n / 2 : n;
long b = (n % 2 == 0) ? n + 1 : (n + 1) / 2;
if (dOf(a) * dOf(b) > t) { System.out.println(a * b); return; }
}
}
}
Starter — Python.
def d_of(n):
# TODO: number of divisors via trial division
return 0
if __name__ == "__main__":
t = int(input())
n = 1
while True:
a, b = (n // 2, n + 1) if n % 2 == 0 else (n, (n + 1) // 2)
if d_of(a) * d_of(b) > t:
print(a * b)
break
n += 1
Evaluation. For t = 5, the answer is 28 (T_7, divisors 1,2,4,7,14,28). For t = 500, the answer is 76576500.
Advanced Tasks (5)¶
Task 11 — d/σ for one huge n via precomputed base primes¶
Problem. Sieve base primes up to √(MAX) once (with MAX = 10^{14}), then answer q queries computing d(x) and σ(x) for x ≤ 10^{14} by trial-dividing with the base primes. Memory must be O(√MAX).
Input / Output spec. Input q, then q values x. Output d(x) and σ(x) per query.
Constraints. 1 ≤ q ≤ 10^4, 1 ≤ x ≤ 10^{14}.
Hint. Base primes up to 10^7 suffice for x ≤ 10^{14}. After dividing out all base primes, a leftover > 1 is a single prime (since any composite leftover would have a factor ≤ √x ≤ 10^7). Handle that leftover prime.
Starter — Go.
package main
import "fmt"
func basePrimes(limit int) []int { /* TODO: simple sieve */ return nil }
func dSigma(x int64, primes []int) (int64, int64) {
// TODO: trial-divide by base primes; handle leftover prime
return 0, 0
}
func main() {
primes := basePrimes(10_000_000)
var q int
fmt.Scan(&q)
for ; q > 0; q-- {
var x int64
fmt.Scan(&x)
d, s := dSigma(x, primes)
fmt.Println(d, s)
}
}
Starter — Java.
import java.util.*;
public class Task11 {
static int[] basePrimes(int limit) { /* TODO */ return new int[0]; }
static long[] dSigma(long x, int[] primes) { /* TODO */ return new long[]{0, 0}; }
public static void main(String[] args) {
int[] primes = basePrimes(10_000_000);
Scanner sc = new Scanner(System.in);
int q = sc.nextInt();
StringBuilder sb = new StringBuilder();
while (q-- > 0) {
long[] r = dSigma(sc.nextLong(), primes);
sb.append(r[0]).append(' ').append(r[1]).append('\n');
}
System.out.print(sb);
}
}
Starter — Python.
def base_primes(limit):
# TODO: simple sieve
return []
def d_sigma(x, primes):
# TODO: trial-divide by base primes; handle leftover prime
return 0, 0
if __name__ == "__main__":
import sys
primes = base_primes(10_000_000)
it = iter(sys.stdin.read().split())
q = int(next(it))
out = []
for _ in range(q):
x = int(next(it))
d, s = d_sigma(x, primes)
out.append(f"{d} {s}")
print("\n".join(out))
Evaluation. dSigma(999_999_999_999_989, ...) (a prime) returns (2, 999_999_999_999_990); dSigma(100_000_000_000_000, ...) = dSigma(2^14·5^14, ...) returns (225, ...) — verify against the formula.
Task 12 — Count primes' contribution: numbers with exactly K divisors¶
Problem. Given N and K, count how many n ≤ N have exactly K divisors (d(n) = K).
Input / Output spec. Input N, K; output the count.
Constraints. 1 ≤ N ≤ 10^7, 1 ≤ K ≤ 1000.
Hint. Sieve d (use the divisor sieve or linear sieve), then count n with d[n] == K. Note d(n)=2 ⇔ n prime, so this also counts primes when K=2.
Starter — Go.
package main
import "fmt"
func dSieve(N int) []int { /* TODO */ return nil }
func main() {
var N, K int
fmt.Scan(&N, &K)
d := dSieve(N)
cnt := 0
for n := 1; n <= N; n++ {
if d[n] == K {
cnt++
}
}
fmt.Println(cnt)
}
Starter — Java.
import java.util.*;
public class Task12 {
static int[] dSieve(int N) { /* TODO */ return new int[N + 1]; }
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt(), K = sc.nextInt();
int[] d = dSieve(N);
int cnt = 0;
for (int n = 1; n <= N; n++) if (d[n] == K) cnt++;
System.out.println(cnt);
}
}
Starter — Python.
def d_sieve(N):
# TODO
return [0] * (N + 1)
if __name__ == "__main__":
N, K = map(int, input().split())
d = d_sieve(N)
print(sum(1 for n in range(1, N + 1) if d[n] == K))
Evaluation. For N=100, K=2 the count is 25 (primes ≤ 100). For N=100, K=1 it is 1 (only n=1).
Task 13 — Sum of d(n) up to N and the Dirichlet hyperbola method¶
Problem. Compute D(N) = Σ_{n=1}^{N} d(n) in O(√N) using the hyperbola method, without a full sieve. Verify it matches Σ ⌊N/i⌋.
Input / Output spec. Input N; output D(N).
Constraints. 1 ≤ N ≤ 10^{12}.
Hint. D(N) = Σ_{i=1}^{N} ⌊N/i⌋ = 2·Σ_{i=1}^{⌊√N⌋} ⌊N/i⌋ − ⌊√N⌋² (count lattice points under the hyperbola xy ≤ N, doubling the region below the diagonal and subtracting the square counted twice).
Starter — Go.
package main
import (
"fmt"
"math"
)
func D(N int64) int64 {
s := int64(math.Sqrt(float64(N)))
for s*s > N {
s--
}
for (s+1)*(s+1) <= N {
s++
}
// TODO: 2*sum_{i=1..s} floor(N/i) - s*s
return 0
}
func main() {
var N int64
fmt.Scan(&N)
fmt.Println(D(N))
}
Starter — Java.
import java.util.*;
public class Task13 {
static long D(long N) {
long s = (long) Math.sqrt((double) N);
while (s * s > N) s--;
while ((s + 1) * (s + 1) <= N) s++;
// TODO: 2*sum floor(N/i) - s*s
return 0;
}
public static void main(String[] args) {
System.out.println(D(new Scanner(System.in).nextLong()));
}
}
Starter — Python.
import math
def D(N):
s = math.isqrt(N)
# TODO: 2*sum(N//i for i in 1..s) - s*s
return 0
if __name__ == "__main__":
print(D(int(input())))
Evaluation. D(10)=27, D(100)=482, D(1000)=7069. Cross-check small N against a brute Σ d(n).
Task 14 — Robin's inequality probe¶
Problem. For all n in [2, N], find any n > 5040 violating Robin's inequality σ(n) < e^γ · n · ln(ln(n)) (none should exist if RH holds). Report violators or "none".
Input / Output spec. Input N; output each violating n, or none.
Constraints. 5041 ≤ N ≤ 5·10^6.
Hint. Sieve σ (64-bit). Use e^γ ≈ 1.7810724179901979. Compare σ(n) (as a float) to EGAMMA * n * math.log(math.log(n)). Watch float precision near the boundary.
Starter — Go.
package main
import (
"fmt"
"math"
)
const eGamma = 1.7810724179901979
func sigmaSieve(N int) []int64 { /* TODO */ return nil }
func main() {
var N int
fmt.Scan(&N)
sig := sigmaSieve(N)
any := false
for n := 5041; n <= N; n++ {
bound := eGamma * float64(n) * math.Log(math.Log(float64(n)))
if float64(sig[n]) >= bound {
fmt.Println(n)
any = true
}
}
if !any {
fmt.Println("none")
}
}
Starter — Java.
import java.util.*;
public class Task14 {
static final double E_GAMMA = 1.7810724179901979;
static long[] sigmaSieve(int N) { /* TODO */ return new long[N + 1]; }
public static void main(String[] args) {
int N = new Scanner(System.in).nextInt();
long[] sig = sigmaSieve(N);
boolean any = false;
for (int n = 5041; n <= N; n++) {
double bound = E_GAMMA * n * Math.log(Math.log(n));
if (sig[n] >= bound) { System.out.println(n); any = true; }
}
if (!any) System.out.println("none");
}
}
Starter — Python.
import math
E_GAMMA = 1.7810724179901979
def sigma_sieve(N):
# TODO
return [0] * (N + 1)
if __name__ == "__main__":
N = int(input())
sig = sigma_sieve(N)
any_viol = False
for n in range(5041, N + 1):
bound = E_GAMMA * n * math.log(math.log(n))
if sig[n] >= bound:
print(n)
any_viol = True
if not any_viol:
print("none")
Evaluation. For any N ≤ 5·10^6, the output should be none (no violator above 5040 is known; 5040 itself is the largest violator). This demonstrates σ's extremal order in practice.
Task 15 — Benchmark: divisor sieve vs linear sieve¶
Problem. Compare the O(N log N) divisor sieve against the O(N) linear sieve for computing d/σ, across increasing N. Validate both produce identical arrays, then report timings.
Input / Output spec. No input; print N and the time for each method.
Constraints. Test N ∈ {10^5, 10^6, 5·10^6}. Both methods must agree on all values.
Hint. Build both arrays, assert equality, then time each. Observe where the linear sieve's O(N) overtakes the divisor sieve's O(N log N) (and note the divisor sieve's better cache behavior at moderate N).
Starter — Go.
package main
import (
"fmt"
"time"
)
func divisorSieve(N int) ([]int, []int64) { /* TODO */ return nil, nil }
func linearSieve(N int) ([]int, []int64) { /* TODO */ return nil, nil }
func main() {
for _, N := range []int{100_000, 1_000_000, 5_000_000} {
t1 := time.Now()
d1, s1 := divisorSieve(N)
dt1 := time.Since(t1)
t2 := time.Now()
d2, s2 := linearSieve(N)
dt2 := time.Since(t2)
ok := true
for i := 1; i <= N; i++ {
if d1[i] != d2[i] || s1[i] != s2[i] {
ok = false
break
}
}
fmt.Printf("N=%8d divisor=%v linear=%v agree=%v\n", N, dt1, dt2, ok)
}
}
Starter — Java.
public class Task15 {
static int[] d; static long[] s;
static void divisorSieve(int N) { /* TODO */ }
static int[] d2; static long[] s2;
static void linearSieve(int N) { /* TODO */ }
public static void main(String[] args) {
for (int N : new int[]{100_000, 1_000_000, 5_000_000}) {
long t1 = System.nanoTime(); divisorSieve(N); long dt1 = System.nanoTime() - t1;
long t2 = System.nanoTime(); linearSieve(N); long dt2 = System.nanoTime() - t2;
boolean ok = true;
for (int i = 1; i <= N; i++) if (d[i] != d2[i] || s[i] != s2[i]) { ok = false; break; }
System.out.printf("N=%8d divisor=%.1fms linear=%.1fms agree=%b%n",
N, dt1 / 1e6, dt2 / 1e6, ok);
}
}
}
Starter — Python.
import time
def divisor_sieve(N): # TODO
return [], []
def linear_sieve(N): # TODO
return [], []
if __name__ == "__main__":
for N in (100_000, 1_000_000, 5_000_000):
t1 = time.perf_counter(); d1, s1 = divisor_sieve(N); dt1 = time.perf_counter() - t1
t2 = time.perf_counter(); d2, s2 = linear_sieve(N); dt2 = time.perf_counter() - t2
ok = d1 == d2 and s1 == s2
print(f"N={N:8d} divisor={dt1*1000:.1f}ms linear={dt2*1000:.1f}ms agree={ok}")
Evaluation. Both methods must agree on all values. Report timings; expect the linear sieve to win at large N, while the divisor sieve may be competitive (better cache locality) at moderate N.
Evaluation Criteria (All Tasks)¶
- Correctness on small inputs first. Validate against the closed-form formulas and a brute-force divisor walk before scaling up.
- Edge cases. Handle
n = 1(d=σ=1, empty product), primes, prime powers, and perfect squares (count√nonce when pairing). - Integer width. Always 64-bit for
σandσ_k; the leftover-prime tail after trial division is mandatory. - Complexity. Single-number tasks should hit
O(√n); all-ntasksO(N log N)(divisor sieve) orO(N)(linear sieve); range sumsO(1)via prefix sums. - Modular care. Under a modulus, accumulate the geometric sum by addition; do not use the division closed form without a verified modular inverse.
- Validation. Cross-check
d(360)=24,σ(360)=1170,σ(6)=12, and perfect numbers6,28,496,8128; a sieve can be wrong on a single value among millions.
Work through the tasks in order: Tasks 1–5 cement single-number computation and the divisor sieve, Tasks 6–10 add the linear sieve, amicable/highly-composite numbers, σ_k, and a classic problem, and Tasks 11–15 push into huge-n per-query factorization, the hyperbola method, asymptotics probes, and benchmarking.