All Euler problems
Project Euler

Triangular Number Intersections

Let T_n = n(n+1)/2 be the n -th triangular number. Find the number of ordered pairs (a, b) with 1 <= a < b <= 10^6 such that T_a + T_b is also a triangular number.

Source sync Apr 19, 2026
Problem #0932
Level Level 11
Solved By 1,877
Languages C++, Python
Answer 72673459417881349
Length 310 words
algebramodular_arithmeticnumber_theory

Problem Statement

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

For the year \(2025\) \[2025 = (20 + 25)^2\] Given positive integers \(a\) and \(b\), the concatenation \(ab\) we call a \(2025\)-number if \(ab = (a+b)^2\).

Other examples are \(3025\) and \(81\).

Note \(9801\) is not a \(2025\)-number because the concatenation of \(98\) and \(1\) is \(981\).

Let \(T(n)\) be the sum of all \(2025\)-numbers with \(n\) digits or less. You are given \(T(4) = 5131\).

Find \(T(16)\).

Problem 932: Triangular Number Intersections

Mathematical Foundation

Theorem 1 (Triangular characterization). An integer m0m \geq 0 is a triangular number if and only if 8m+18m + 1 is a perfect square.

Proof. (\Rightarrow) If m=k(k+1)/2m = k(k+1)/2 for some non-negative integer kk, then 8m+1=4k2+4k+1=(2k+1)28m + 1 = 4k^2 + 4k + 1 = (2k+1)^2, which is a perfect square.

(\Leftarrow) If 8m+1=s28m + 1 = s^2 for some positive integer ss, then ss must be odd (since 8m+18m + 1 is odd), say s=2k+1s = 2k + 1. Then 8m+1=4k2+4k+18m + 1 = 4k^2 + 4k + 1, giving m=k(k+1)/2=Tkm = k(k+1)/2 = T_k. \square

Theorem 2 (Reduction to near-Pythagorean equation). Ta+TbT_a + T_b is triangular if and only if (2a+1)2+(2b+1)21(2a+1)^2 + (2b+1)^2 - 1 is a perfect square.

Proof. By Theorem 1, Ta+TbT_a + T_b is triangular iff 8(Ta+Tb)+18(T_a + T_b) + 1 is a perfect square. Now:

8(Ta+Tb)+1=8a(a+1)+b(b+1)2+1=4a2+4a+4b2+4b+1=(2a+1)2+(2b+1)21.8(T_a + T_b) + 1 = 8 \cdot \frac{a(a+1) + b(b+1)}{2} + 1 = 4a^2 + 4a + 4b^2 + 4b + 1 = (2a+1)^2 + (2b+1)^2 - 1.

\square

Lemma 1 (Parametric families). Setting X=2a+1X = 2a+1, Y=2b+1Y = 2b+1, Z2=X2+Y21Z^2 = X^2 + Y^2 - 1, the equation X2+Y2Z2=1X^2 + Y^2 - Z^2 = 1 with X,YX, Y odd and 3X<Y3 \leq X < Y parametrizes all valid pairs. Solutions arise from:

  • Pythagorean-like triples: if (X,Y,Z)(X, Y, Z) satisfies X2+Y2=Z2+1X^2 + Y^2 = Z^2 + 1, then each solution yields a=(X1)/2a = (X-1)/2, b=(Y1)/2b = (Y-1)/2.
  • Recurrence relations generated by the automorphisms of the quadratic form X2+Y2Z2=1X^2 + Y^2 - Z^2 = 1.

Proof. The substitution is direct from Theorem 2. The equation X2+Y2Z2=1X^2 + Y^2 - Z^2 = 1 defines a quadric surface over Z\mathbb{Z}, and its integer points can be enumerated via descent or parametric families derived from the group structure of the associated orthogonal group. \square

Editorial

Count pairs (a, b) with 1 <= a < b <= limit where T_a + T_b is itself a triangular number, i.e. T_a + T_b = T_c for some c >= 1. Key identity: T_a + T_b = a(a+1)/2 + b(b+1)/2 = (a^2 + b^2 + a + b) / 2. This equals T_c = c(c+1)/2 iff a^2 + b^2 + a + b = c(c+1), i.e. 4(a^2 + b^2 + a + b) + 1 = (2c+1)^2, so we need 2(2a+1)^2 + 2(2b+1)^2 - 1 to be a perfect square (of the form (2c+1)^2). We iterate over a from 1 to N-1.

Pseudocode

for a from 1 to N-1
for a from 1 to N-1
For each factorization K = d * e with d < e, d ≡ e (mod 2):

Complexity Analysis

  • Time (brute force): O(N2)O(N^2) with O(1)O(1) integer square root test per pair.
  • Time (optimized): O(Nd(N))O(N \cdot d(N)) where d(N)d(N) is the average number of divisors, approximately O(NlogN)O(N \log N).
  • Space: O(1)O(1) auxiliary (or O(N)O(N) if precomputing divisors).

Answer

72673459417881349\boxed{72673459417881349}

Code

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

C++ project_euler/problem_932/solution.cpp
#include <bits/stdc++.h>
using namespace std;
int main(){
    const int LIM=10000;
    set<long long> tri;
    for(long long n=1;n*(n+1)/2<=2LL*LIM*(LIM+1);n++) tri.insert(n*(n+1)/2);
    int cnt=0;
    for(int a=1;a<=LIM;a++){
        long long ta=(long long)a*(a+1)/2;
        for(int b=a+1;b<=LIM;b++){
            long long tb=(long long)b*(b+1)/2;
            if(tri.count(ta+tb)) cnt++;
        }
    }
    cout<<cnt<<endl;
    return 0;
}