All Euler problems
Project Euler

Investigating the Torricelli Point of a Triangle

Let ABC be a triangle with all interior angles less than 120 degrees. Let T be the Torricelli (Fermat) point of the triangle, and let p = |AT|, q = |BT|, r = |CT|. It can be shown that p, q, r sati...

Source sync Apr 19, 2026
Problem #0143
Level Level 08
Solved By 3,265
Languages C++, Python
Answer 30758397
Length 454 words
geometrynumber_theorygraph

Problem Statement

This archive keeps the full statement, math, and original media on the page.

Let \(ABC\) be a triangle with all interior angles being less than \(120\) degrees. Let \(X\) be any point inside the triangle and let \(XA = p\), \(XC = q\), and \(XB = r\). co

Fermat challenged Torricelli to find the position of \(X\) such that \(p + q + r\) was minimised.

Torricelli was able to prove that if equilateral triangles \(AOB\), \(BNC\) and \(AMC\) are constructed on each side of triangle \(ABC\), the circumscribed circles of \(AOB\), \(BNC\), and \(AMC\) will intersect at a single point, \(T\), inside the triangle. Moreover he proved that \(T\), called the Torricelli/Fermat point, minimises \(p + q + r\). Even more remarkable, it can be shown that when the sum is minimised, \(AN = BM = CO = p + q + r\) and that \(AN\), \(BM\) and \(CO\) also intersect at \(T\).

PIC

If the sum is minimised and \(a, b, c, p, q\) and \(r\) are all positive integers we shall call triangle \(ABC\) a Torricelli triangle. For example, \(a = 399\), \(b = 455\), \(c = 511\) is an example of a Torricelli triangle, with \(p + q + r = 784\).

Find the sum of all distinct values of \(p + q + r \le 120000\) for Torricelli triangles.

Problem 143: Investigating the Torricelli Point of a Triangle

Mathematical Foundation

Theorem 1. At the Torricelli point T of a triangle with all angles less than 120°120°, each pair of vertices subtends an angle of exactly 120°120° at T. In particular, for side c=ABc = |AB|:

c2=p2+pq+q2c^2 = p^2 + pq + q^2

Proof. The Torricelli point minimizes AT+BT+CT|AT| + |BT| + |CT| and, when all angles are less than 120°120°, lies in the interior with ATB=BTC=ATC=120°\angle ATB = \angle BTC = \angle ATC = 120°. Applying the law of cosines to triangle ATB:

c2=p2+q22pqcos(120°)=p2+q22pq(12)=p2+pq+q2c^2 = p^2 + q^2 - 2pq\cos(120°) = p^2 + q^2 - 2pq \cdot (-\tfrac{1}{2}) = p^2 + pq + q^2

The other two equations follow by cyclic symmetry. \square

Definition. A pair (u,v)(u, v) with uv1u \geq v \geq 1 is called 120-compatible if u2+uv+v2u^2 + uv + v^2 is a perfect square.

Theorem 2. All primitive 120-compatible pairs (with gcd(u,v)=1\gcd(u,v) = 1) are parametrized by:

u=m2n2,v=2mn+n2u = m^2 - n^2, \quad v = 2mn + n^2

where m>n1m > n \geq 1, gcd(m,n)=1\gcd(m, n) = 1, and m≢n(mod3)m \not\equiv n \pmod{3}. The corresponding square root is s=m2+mn+n2s = m^2 + mn + n^2.

Proof. We verify: u2+uv+v2=(m2n2)2+(m2n2)(2mn+n2)+(2mn+n2)2u^2 + uv + v^2 = (m^2 - n^2)^2 + (m^2 - n^2)(2mn + n^2) + (2mn + n^2)^2.

Expanding each term:

  • (m2n2)2=m42m2n2+n4(m^2 - n^2)^2 = m^4 - 2m^2 n^2 + n^4
  • (m2n2)(2mn+n2)=2m3n+m2n22mn3n4(m^2 - n^2)(2mn + n^2) = 2m^3 n + m^2 n^2 - 2mn^3 - n^4
  • (2mn+n2)2=4m2n2+4mn3+n4(2mn + n^2)^2 = 4m^2 n^2 + 4mn^3 + n^4

Summing: m4+2m3n+3m2n2+2mn3+n4=(m2+mn+n2)2m^4 + 2m^3 n + 3m^2 n^2 + 2mn^3 + n^4 = (m^2 + mn + n^2)^2.

For primitivity: if 3(mn)3 \mid (m - n), then mn(mod3)m \equiv n \pmod{3}, which implies u=m2n20(mod3)u = m^2 - n^2 \equiv 0 \pmod{3} and v=2mn+n22n2+n2=3n20(mod3)v = 2mn + n^2 \equiv 2n^2 + n^2 = 3n^2 \equiv 0 \pmod{3}, so gcd(u,v)3\gcd(u,v) \geq 3, violating primitivity. The converse (that gcd(m,n)=1\gcd(m,n) = 1 and m≢n(mod3)m \not\equiv n \pmod{3} imply gcd(u,v)=1\gcd(u,v) = 1) can be verified by checking that any common prime factor of uu and vv must divide m2+mn+n2=sm^2 + mn + n^2 = s, and showing this leads to a contradiction using the Eisenstein integer norm. \square

Lemma 1. All 120-compatible pairs are of the form (ku,kv)(ku, kv) where (u,v)(u,v) is a primitive pair and k1k \geq 1.

Proof. If (U,V)(U, V) is 120-compatible with g=gcd(U,V)g = \gcd(U, V), then U2+UV+V2=g2(u2+uv+v2)U^2 + UV + V^2 = g^2(u^2 + uv + v^2) where u=U/gu = U/g, v=V/gv = V/g, gcd(u,v)=1\gcd(u,v) = 1. Since u2+uv+v2u^2 + uv + v^2 is a perfect square (being g2g^{-2} times a perfect square), (u,v)(u,v) is a primitive 120-compatible pair. \square

Lemma 2. A valid Torricelli triple (p,q,r)(p, q, r) corresponds to a 3-clique in the graph GG whose vertices are positive integers and whose edges connect all 120-compatible pairs.

Proof. The three Torricelli equations require (p,q)(p,q), (p,r)(p,r), and (q,r)(q,r) to each be 120-compatible. This is exactly the condition that {p,q,r}\{p, q, r\} forms a clique of size 3 in GG. \square

Editorial

At the Torricelli point T, angles ATB = BTC = CTA = 120 degrees. By cosine rule: a^2 = q^2 + qr + r^2, etc. We need p, q, r positive integers with p^2+pq+q^2, p^2+pr+r^2, q^2+qr+r^2 all perfect squares, and p+q+r <= 120000. 120-compatible pairs: (u,v) with u^2+uv+v^2 a perfect square. Primitive parametrization: u = m^2-n^2, v = 2mn+n^2 with m > n >= 1, gcd(m,n) = 1, (m-n) not divisible by 3. Then u^2+uv+v^2 = (m^2+mn+n^2)^2. All solutions are k*(u,v) for positive integer k. We generate all 120-compatible pairs. We then add both orderings. Finally, also consider (v0, u0) as a pair (swap roles).

Pseudocode

INPUT: L = 120000
OUTPUT: Sum of all distinct values p+q+r <= L
GENERATE ALL 120-COMPATIBLE PAIRS:
Add both orderings
Also consider (v0, u0) as a pair (swap roles)
Similarly for (v0, u0) primitive pair if v0 > u0
FIND ALL 3-CLIQUES:
for each vertex p in pairs
RETURN sum of all elements in sums

Complexity Analysis

  • Time: Pair generation is O(LM)O(L \cdot M) where MM is the number of primitive pairs with parameters up to L\sqrt{L}, which is O(L/logL)O(L / \log L) by density estimates for Eisenstein primes. Clique enumeration depends on graph density; in practice, the neighbor sets are small enough that intersection is fast. Overall: O(L3/2)O(L^{3/2}) in the worst case.
  • Space: O(L+E)O(L + E) where EE is the number of 120-compatible pairs, for storing the adjacency lists.

Answer

30758397\boxed{30758397}

Code

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

C++ project_euler/problem_143/solution.cpp
#include <bits/stdc++.h>
using namespace std;

int main() {
    // Problem 143: Torricelli point distances
    // Find sum of all distinct p+q+r <= 120000
    // where all three pair-wise expressions u^2+uv+v^2 are perfect squares.
    //
    // Primitive 120-compatible pairs: u = m^2-n^2, v = 2mn+n^2
    // with m > n >= 1, gcd(m,n) = 1, (m-n) % 3 != 0.
    // Then u^2+uv+v^2 = (m^2+mn+n^2)^2.
    // All solutions are k*(u,v) for k >= 1.

    const int LIMIT = 120000;

    // smaller[u] = sorted vector of v < u compatible with u
    vector<vector<int>> smaller(LIMIT + 1);

    auto addPrimitive = [&](int a, int b) {
        if (a <= 0 || b <= 0) return;
        int u = max(a, b), v = min(a, b);
        for (int k = 1; (long long)k * (u + v) <= LIMIT; k++) {
            smaller[k * u].push_back(k * v);
        }
    };

    for (int m = 2; (long long)m * m < LIMIT; m++) {
        for (int n = 1; n < m; n++) {
            if (__gcd(m, n) != 1) continue;
            if ((m - n) % 3 == 0) continue;
            int a = m * m - n * n;
            int b = 2 * m * n + n * n;
            addPrimitive(a, b);
        }
    }

    // Sort and deduplicate each adjacency list
    for (int i = 0; i <= LIMIT; i++) {
        sort(smaller[i].begin(), smaller[i].end());
        smaller[i].erase(unique(smaller[i].begin(), smaller[i].end()), smaller[i].end());
    }

    // Find triangles
    set<int> valid_sums;

    for (int p = 1; p <= LIMIT; p++) {
        if (smaller[p].empty()) continue;
        // For quick lookup, use a set for smaller[p]
        unordered_set<int> sp_set(smaller[p].begin(), smaller[p].end());

        for (int q : smaller[p]) {
            int max_r = LIMIT - p - q;
            if (max_r <= 0) continue;

            for (int r : smaller[q]) {
                if (r >= q) continue;
                if (r > max_r) continue;
                if (sp_set.count(r)) {
                    valid_sums.insert(p + q + r);
                }
            }
        }
    }

    long long ans = 0;
    for (int s : valid_sums) ans += s;
    cout << ans << endl;

    return 0;
}