Counting Fractions
Consider the fraction n/d, where n and d are positive integers. If n < d and gcd(n, d) = 1, it is called a reduced proper fraction. How many elements are in the set of reduced proper fractions for...
Problem Statement
This archive keeps the full statement, math, and original media on the page.
Consider the fraction, \(\dfrac n d\), where \(n\) and \(d\) are positive integers. If \(n < d\) and \(\operatorname {HCF}(n,d)=1\), it is called a reduced proper fraction.
If we list the set of reduced proper fractions for \(d \le 8\) in ascending order of size, we get: \[\frac 1 8, \frac 1 7, \frac 1 6, \frac 1 5, \frac 1 4, \frac 2 7, \frac 1 3, \frac 3 8, \frac 2 5, \frac 3 7, \frac 1 2, \frac 4 7, \frac 3 5, \frac 5 8, \frac 2 3, \frac 5 7, \frac 3 4, \frac 4 5, \frac 5 6, \frac 6 7, \frac 7 8\] It can be seen that there are \(21\) elements in this set.
How many elements would be contained in the set of reduced proper fractions for \(d \le 1\,000\,000\)
Problem 72: Counting Fractions
Mathematical Analysis
Theorem 1 (Fractions Per Denominator)
The number of reduced proper fractions with denominator exactly is .
Proof. A fraction with is in lowest terms if and only if . By definition, . For , since , the element does not contribute, so the count of with and equals .
Theorem 2 (Euler’s Product Formula)
For :
Proof. We prove two properties and combine them.
(i) Multiplicativity. If , then . By the Chinese Remainder Theorem, the canonical ring isomorphism restricts to a group isomorphism . Comparing cardinalities gives .
(ii) Prime powers. For a prime power , an integer satisfies if and only if . There are such multiples, so .
Applying (i) inductively to the prime factorization and substituting (ii) yields the product formula.
Theorem 3 (Answer Formula)
The total number of reduced proper fractions with denominator is:
Proof. By Theorem 1, the count is . (We begin at since admits no proper fractions: the condition has no solutions.) Since , this equals .
Lemma (Totient Sieve Correctness)
The sieve algorithm that initializes for all and, for each prime , updates for all multiples of , correctly computes for all .
Proof. After the sieve completes, each entry satisfies:
Every prime dividing satisfies , so the product ranges over all prime divisors of . By Theorem 2, this equals .
Primes are correctly identified during the sieve: is prime if and only if when is first visited (since all primes dividing would have already modified , and is composite if and only if it has such a prime divisor).
Remark (Asymptotic)
By a classical result in analytic number theory, . For , this gives approximately .
Editorial
The denominator-by-denominator interpretation is the key simplification. For a fixed , exactly numerators produce reduced proper fractions, so the whole problem becomes the summatory totient
Computing each independently would waste work because nearby values share prime factors. The sieve avoids that. We begin with for every , and whenever we discover a prime , we apply the factor to every multiple of . By the time the sieve finishes, every denominator has been filtered by exactly its distinct prime divisors, so the array contains the correct totients and summing it gives the answer.
Pseudocode
Create an array phi with phi[d] = d for every d from 0 to N.
For each integer p from 2 to N:
If phi[p] is still equal to p, then p is prime
For each multiple m of p:
replace phi[m] by phi[m] x (p - 1) / p
Add phi[2] through phi[N].
Return that total.
Complexity Analysis
Time: The sieve visits, for each prime , all multiples. By Mertens’ second theorem:
where is the Meissel—Mertens constant.
- Time: .
- Space: for the array .
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#include <bits/stdc++.h>
using namespace std;
int main() {
// Count reduced proper fractions n/d with d <= 1,000,000.
// Answer = sum of phi(d) for d = 2 to N (Theorem 3).
// Euler totient sieve in O(N log log N).
const int N = 1000000;
vector<int> phi(N + 1);
iota(phi.begin(), phi.end(), 0); // phi[i] = i
for (int p = 2; p <= N; p++) {
if (phi[p] == p) { // p is prime
for (int m = p; m <= N; m += p) {
phi[m] = phi[m] / p * (p - 1);
}
}
}
long long total = 0;
for (int d = 2; d <= N; d++) {
total += phi[d];
}
cout << total << endl;
return 0;
}
"""
Project Euler Problem 72: Counting Fractions
Count the number of reduced proper fractions n/d with d <= 1,000,000.
By Theorem 3, the answer is sum of phi(d) for d = 2 to 1,000,000.
Computed via Euler totient sieve in O(N log log N).
"""
def solve_sieve(N: int) -> int:
"""Compute sum of phi(d) for d=2..N using Euler totient sieve."""
phi = list(range(N + 1))
for p in range(2, N + 1):
if phi[p] == p: # p is prime
for m in range(p, N + 1, p):
phi[m] = phi[m] // p * (p - 1)
return sum(phi[d] for d in range(2, N + 1))
answer = solve_sieve(1_000_000)
print(answer)