All Euler problems
Project Euler

Project Euler Problem 454: Diophantine Reciprocals III

In the equation 1/x + 1/y = 1/n, where x, y, and n are positive integers, define F(L) as the number of solutions satisfying x < y <= L. Checkpoints: F(15) = 4 F(1000) = 1069 Find F(10^12).

Source sync Apr 19, 2026
Problem #0454
Level Level 21
Solved By 572
Languages C++, Python
Answer 5435004633092
Length 411 words
number_theorymodular_arithmeticoptimization

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 a limit $L$ we define $F(L)$ as the number of solutions which satisfy $x < y \le L$.

We can verify that $F(15) = 4$ and $F(1000) = 1069$.

Find $F(10^{12})$.

Project Euler Problem 454: Diophantine Reciprocals III

Mathematical Analysis

Step 1: Parametrize Solutions

From 1/x + 1/y = 1/n with x < y, substitute x = n + a, y = n + b where a < b and ab = n^2.

Step 2: Coprime Pair Representation

Write n = kuv where gcd(u,v) = 1 and u < v. Then:

  • a = ku^2, b = kv^2
  • x = n + a = ku(u+v), y = n + b = kv(u+v)

The condition y <= L becomes: kv(u+v) <= L, i.e., k <= L / (v*(u+v)).

Step 3: Clean Summation Formula

Every valid solution (x,y) corresponds uniquely to a triple (u, v, k) with:

  • 1 <= u < v, gcd(u, v) = 1, k >= 1
  • kv(u+v) <= L

Therefore:

F(L) = sum_{v=2}^{V} sum_{u=1, gcd(u,v)=1}^{v-1} floor(L / (v*(u+v)))

where V = floor(sqrt(L)) (since v*(u+v) >= v*(v+1) > v^2, we need v^2 < L).

Step 4: Efficient Computation

Mobius inversion on coprimality: For each v, the coprimality condition gcd(u, v) = 1 can be handled via Mobius function:

sum_{u<v, gcd(u,v)=1} floor(L/(v*(u+v)))
= sum_{d|v} mu(d) * sum_{j} floor(L/(v*d*j))

where the j-sum runs over appropriate bounds. Each inner sum is a partial sum of floor(R/j) computable via the hyperbola method in O(sqrt(R)) time.

Direct approach (used in C++): For L = 10^12, v ranges up to ~10^6. For each v, iterate over u coprime to v. With careful implementation and GCD optimization, this runs in reasonable time in C++.

Step 5: Verification

LF(L)
154
10060
10001069
10^415547
10^5203931
10^62524207

Correctness

Theorem. The method described above computes exactly the quantity requested in the problem statement.

Proof. The preceding analysis identifies the admissible objects and derives the formula, recurrence, or exhaustive search carried out by the algorithm. The computation evaluates exactly that specification, so every valid contribution is included once and no invalid contribution is counted. Therefore the returned value is the required answer. \square

Answer

5435004633092\boxed{5435004633092}

Complexity

  • Time: O(sum_{v=2}^{sqrt(L)} phi(v)) ~ O(L / pi^2 * 3) with optimizations
  • In practice ~10^11 operations, feasible in C++ within minutes
  • Space: O(sqrt(L)) for sieve

Code

Each problem page includes the exact C++ and Python source files from the local archive.

C++ project_euler/problem_454/solution.cpp
/**
 * Project Euler Problem 454: Diophantine Reciprocals III
 *
 * In 1/x + 1/y = 1/n (positive integers, x < y), F(L) counts solutions
 * with y <= L. Find F(10^12).
 *
 * Key identity:
 *   F(L) = sum over coprime pairs (u,v) with 1<=u<v
 *          of floor(L / (v*(u+v)))
 *
 * Derivation: x = k*u*(u+v), y = k*v*(u+v), n = k*u*v with gcd(u,v)=1.
 *
 * For each v, we iterate u from 1 to v-1 checking gcd(u,v)=1.
 * v ranges up to sqrt(L) ~ 10^6 for L = 10^12.
 *
 * Compile: g++ -O2 -o solution solution.cpp
 * Run: ./solution [L]  (default L = 10^12)
 */

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <ctime>
#include <algorithm>

using namespace std;
typedef long long ll;
typedef unsigned long long ull;

// Fast GCD
inline ll gcd(ll a, ll b) {
    while (b) { a %= b; ll t = a; a = b; b = t; }
    return a;
}

int main(int argc, char* argv[]) {
    ll L = 1000000000000LL; // 10^12
    if (argc > 1) {
        L = atoll(argv[1]);
    }

    printf("Problem 454: Diophantine Reciprocals III\n");
    printf("Computing F(%lld)...\n", (long long)L);

    clock_t t_start = clock();

    ll v_max = (ll)sqrt((double)L);
    while (v_max * (v_max + 1) > L) v_max--;
    while ((v_max + 1) * (v_max + 2) <= L) v_max++;
    // v_max is the largest v such that v*(v+1) <= L (since u >= 1 means u+v >= v+1)

    printf("v_max = %lld\n", (long long)v_max);

    ll result = 0;

    for (ll v = 2; v <= v_max; v++) {
        for (ll u = 1; u < v; u++) {
            ll denom = v * (u + v);
            if (denom > L) break;
            if (gcd(u, v) == 1) {
                result += L / denom;
            }
        }
        if (v % 100000 == 0) {
            double elapsed = (double)(clock() - t_start) / CLOCKS_PER_SEC;
            printf("  v = %lld / %lld, partial = %lld, time = %.1fs\n",
                   (long long)v, (long long)v_max, (long long)result, elapsed);
        }
    }

    double elapsed = (double)(clock() - t_start) / CLOCKS_PER_SEC;

    printf("\nResult:\n");
    printf("  F(%lld) = %lld\n", (long long)L, (long long)result);
    printf("  Time: %.3f seconds\n", elapsed);

    // Verification
    if (L == 15LL) {
        printf("  Expected: 4 -> %s\n", result == 4 ? "PASS" : "FAIL");
    }
    if (L == 1000LL) {
        printf("  Expected: 1069 -> %s\n", result == 1069 ? "PASS" : "FAIL");
    }
    if (L == 1000000000000LL) {
        printf("  Expected: 5435004633092 -> %s\n",
               result == 5435004633092LL ? "PASS" : "FAIL");
    }

    return 0;
}