Counting Fractions in a Range
How many reduced proper fractions n/d with gcd(n, d) = 1 lie strictly between 1/3 and 1/2 for d <= 12,000?
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, \textcolor{red}{\mathbf{\frac 3 8}}, \textcolor{red}{\mathbf{\frac 2 5}}, \textcolor{red}{\mathbf{\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 $3$ fractions between $\dfrac 1 3$ and $\dfrac 1 2$.
How many fractions lie between $\dfrac 1 3$ and $\dfrac 1 2$ in the sorted set of reduced proper fractions for $d \le 12\,000$?
Problem 73: Counting Fractions in a Range
Mathematical Analysis
Theorem 1 (Range Bounds for Fixed Denominator)
For a fixed denominator , the integers satisfying and are precisely those in the set:
Proof. The condition gives , so (since is a positive integer and may not be an integer). The condition gives , so . The fraction is reduced if and only if .
Theorem 2 (Mobius Identity for Coprimality)
For any positive integers and :
where is the Mobius function and denotes the Iverson bracket.
Proof. Let and define . By the Mobius inversion identity (or equivalently, since is the Dirichlet inverse of the constant function ), we have , where is the identity for Dirichlet convolution: .
Explicitly, for with :
and . Hence .
Theorem 3 (Mobius Summation Formula)
The total count of reduced fractions between and with denominator is:
where counts the total integers in the range summed over denominators (without the coprimality constraint).
Proof. Starting from:
Applying Theorem 2:
Exchanging summation order with the substitutions , :
The inner count equals when this is non-negative, and 0 otherwise. This gives the stated formula.
Remark (Mobius Sieve)
The Mobius function can be computed for all via a sieve analogous to the Sieve of Eratosthenes:
- Initialize for all .
- For each prime : negate for all multiples of ; set for all multiples of .
This correctly computes because: if has a squared prime factor; otherwise where is the number of distinct prime factors, and each prime negation toggles the sign.
Editorial
The direct approach would inspect every denominator , generate the numerators in the interval , and then filter by . The Mobius identity lets us perform that filtering in bulk instead of checking gcds one fraction at a time.
After expanding the coprimality condition with , the problem reorganizes into divisor classes indexed by . For a fixed , we only need to count how many raw numerators fall into the interval for denominators up to ; the Mobius value then decides whether that whole class contributes positively, negatively, or not at all. So the candidates are generated by the interval bounds for each denominator, while the Mobius weights perform the filtering that enforces reduced fractions.
Pseudocode
Sieve the Mobius function up to N.
Set the final count to 0.
For each divisor scale k from 1 to N:
If mu[k] is 0, continue to the next scale
Let limit be floor(N / k)
Set a subtotal for this scale to 0
For each denominator d from 2 to limit:
Let lo be the smallest integer strictly greater than d / 3
Let hi be the largest integer strictly smaller than d / 2
If the interval from lo to hi is nonempty:
add its size to the subtotal
Add mu[k] times this subtotal to the final count
Return the final count.
Complexity Analysis
Mobius sieve: .
Double sum: The total number of iterations is (harmonic sum).
- Time: .
- Space: for the Mobius sieve.
For , this runs in well under a second.
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 fractions n/d with 1/3 < n/d < 1/2, d <= 12000.
// Mobius summation: C(N) = sum_k mu(k) * G(floor(N/k)).
const int N = 12000;
// Sieve the Mobius function
vector<int> mu(N + 1, 1);
vector<bool> is_prime(N + 1, true);
for (int p = 2; p <= N; p++) {
if (is_prime[p]) {
for (int m = 2 * p; m <= N; m += p)
is_prime[m] = false;
for (long long m = (long long)p * p; m <= N; m += (long long)p * p)
mu[m] = 0;
for (int m = p; m <= N; m += p)
mu[m] *= -1;
}
}
long long count = 0;
for (int k = 1; k <= N; k++) {
if (mu[k] == 0) continue;
int limit = N / k;
long long c = 0;
for (int d = 2; d <= limit; d++) {
int lo = d / 3 + 1;
int hi = (d - 1) / 2;
if (hi >= lo) c += hi - lo + 1;
}
count += mu[k] * c;
}
cout << count << endl;
return 0;
}
"""
Project Euler Problem 73: Counting Fractions in a Range
Count reduced fractions n/d strictly between 1/3 and 1/2 with d <= 12000.
By Theorem 3 (Mobius Summation), we sieve mu and sum over divisor classes.
"""
def solve():
N = 12000
# Sieve the Mobius function
mu = [1] * (N + 1)
is_prime = [True] * (N + 1)
for p in range(2, N + 1):
if is_prime[p]:
for m in range(2 * p, N + 1, p):
is_prime[m] = False
for m in range(p * p, N + 1, p * p):
mu[m] = 0
for m in range(p, N + 1, p):
mu[m] *= -1
count = 0
for k in range(1, N + 1):
if mu[k] == 0:
continue
limit = N // k
c = 0
for d in range(2, limit + 1):
lo = d // 3 + 1 # smallest n > d/3
hi = (d - 1) // 2 # largest n < d/2
if hi >= lo:
c += hi - lo + 1
count += mu[k] * c
return count
if __name__ == "__main__":
answer = solve()
assert answer == 7295372
print(answer)