Diophantine Reciprocals I
Find the least value of n such that the number of distinct solutions of (1)/(x) + (1)/(y) = (1)/(n) exceeds 1000.
Problem Statement
This archive keeps the full statement, math, and original media on the page.
In the following equation \(x\), \(y\), and \(n\) are positive integers. \[\dfrac {1}{x} + \dfrac {1}{y} = \dfrac {1}{n}\] For \(n = 4\) there are exactly three distinct solutions: \begin {align} \dfrac {1}{5} + \dfrac {1}{20} &= \dfrac {1}{4}\\ \dfrac {1}{6} + \dfrac {1}{12} &= \dfrac {1}{4}\\ \dfrac {1}{8} + \dfrac {1}{8} &= \dfrac {1}{4} \end {align}
What is the least value of \(n\) for which the number of distinct solutions exceeds one-thousand?
Problem 108: Diophantine Reciprocals I
Mathematical Foundation
Theorem 1. (Algebraic Transformation) The equation with positive integers is equivalent to .
Proof. Starting from , multiply both sides by :
Rearrange: . Add to both sides:
Factor the left side: .
For the constraint : since and , each fraction must be strictly less than , so and , giving and .
Theorem 2. (Solution Count) The number of distinct solutions with equals , where denotes the number of positive divisors of .
Proof. Let , so with . The solutions with correspond to divisor pairs of with (since ). The number of such pairs is : if is a perfect square (which it always is), then is odd, and the number of pairs with is .
Theorem 3. (Divisor Function of a Square) If , then:
Proof. Since , by the multiplicative property of the divisor function:
Each factor counts the number of choices for the exponent of in a divisor of (from to ).
Lemma 1. (Optimization Principle) To minimize subject to , the exponents assigned to primes must satisfy .
Proof. Suppose for some (so ). Swapping exponents does not change but strictly decreases :
since and . Thus assigning larger exponents to smaller primes is always optimal.
Theorem 4. (Solution) We need . Since is odd, this means , i.e., .
The minimum with this property is:
with and .
Proof. We verify is minimal by exhaustive search over non-increasing exponent sequences. The exponent sequence is , giving the divisor product . Any alternative sequence with product assigned to the same or different primes yields . This is verified by checking all feasible exponent profiles (bounded by primes and maximum exponent ).
Editorial
After rewriting the equation as , the search is no longer over pairs at all; it is over factorizations of . If , then the number of solutions depends only on the divisor product , so the task is to find the smallest whose exponent pattern makes that product reach .
The key optimization is that a minimal solution must place larger exponents on smaller primes, which means the exponents form a non-increasing sequence. The implementation recursively builds exactly those sequences, updates both the current value of and the current divisor product, and prunes any branch that is already no better than the best solution found so far.
Pseudocode
Keep a global best value of n, initially infinite.
Explore exponent sequences recursively, one prime at a time.
During the search:
If the current divisor product has already reached 2001, compare the current n with the best value and keep the smaller one.
Otherwise choose an exponent for the next prime, not exceeding the previous exponent.
Update n by multiplying by the corresponding prime power, and update the divisor product by the factor 2a + 1.
Skip any branch whose partial n is already at least as large as the best solution found.
When all feasible branches have been explored or pruned, return the best n.
Complexity Analysis
- Time: The search explores exponent sequences with . The number of such sequences is bounded by the number of partitions of integers into parts of the form , which is very small (hundreds at most). With pruning (), the search terminates almost instantly.
- Space: for the recursion stack, where (the number of primes considered).
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 108: Diophantine Reciprocals I
*
* 1/x + 1/y = 1/n => (x-n)(y-n) = n^2
* Number of solutions = ceil(d(n^2) / 2) where d is the divisor function.
* d(n^2) = product of (2*a_i + 1) for each prime factor p_i^a_i of n.
* We need ceil(d(n^2)/2) > 1000, i.e., d(n^2) >= 2001.
*
* Strategy: search over non-increasing exponent sequences assigned to
* primes 2, 3, 5, 7, 11, 13, ... to minimize n.
*/
int primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47};
const int NPRIMES = 15;
long long best_n;
// Recursive search: assign exponents to primes in order
// idx: current prime index, max_exp: maximum exponent allowed (non-increasing)
// current_n: product so far, current_div: d(n^2) so far
void dfs(int idx, int max_exp, long long current_n, long long current_div) {
if (current_div >= 2001) {
best_n = min(best_n, current_n);
return;
}
if (idx >= NPRIMES) return;
if (current_n > best_n) return;
// Try exponents from max_exp down to 1
long long pw = 1;
for (int e = 1; e <= max_exp; e++) {
pw *= primes[idx];
if (current_n > best_n / pw) break; // overflow guard
dfs(idx + 1, e, current_n * pw, current_div * (2 * e + 1));
}
}
int main() {
best_n = LLONG_MAX;
dfs(0, 30, 1, 1);
cout << best_n << endl;
return 0;
}
"""
Problem 108: Diophantine Reciprocals I
1/x + 1/y = 1/n => (x-n)(y-n) = n^2
Number of solutions = ceil(d(n^2) / 2)
d(n^2) = product of (2*a_i + 1) for prime factorization n = prod(p_i^a_i)
Need d(n^2) >= 2001.
Minimize n by searching over non-increasing exponent sequences
assigned to primes 2, 3, 5, 7, ...
"""
import math
PRIMES = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
best_n = float('inf')
def search(idx, max_exp, current_n, current_div):
global best_n
if current_div >= 2001:
best_n = min(best_n, current_n)
return
if idx >= len(PRIMES):
return
if current_n >= best_n:
return
pw = 1
for e in range(1, max_exp + 1):
pw *= PRIMES[idx]
if current_n * pw >= best_n:
break
search(idx + 1, e, current_n * pw, current_div * (2 * e + 1))
search(0, 30, 1, 1)
print(best_n)
# Verification
if __name__ == "__main__":
n = best_n
# Factor n to verify
temp = n
factors = {}
for p in PRIMES:
while temp % p == 0:
factors[p] = factors.get(p, 0) + 1
temp //= p
d_n2 = 1
for a in factors.values():
d_n2 *= (2 * a + 1)
solutions = (d_n2 + 1) // 2
print(f"n = {n}, factorization = {factors}")
print(f"d(n^2) = {d_n2}, solutions = {solutions}")