All Euler problems
Project Euler

Prime Pair Connection

For consecutive primes p_1 and p_2 where 5 <= p_1 and p_2 <= 1,000,003, find S(p_1, p_2), the smallest positive integer whose last digits equal p_1 and which is divisible by p_2. Find sum S(p_1, p_...

Source sync Apr 19, 2026
Problem #0134
Level Level 05
Solved By 8,127
Languages C++, Python
Answer 18613426663617118
Length 181 words
modular_arithmeticnumber_theorylinear_algebra

Problem Statement

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

Consider the consecutive primes \(p_1 = 19\) and \(p_2 = 23\). It can be verified that \(1219\) is the smallest number such that the last digits are formed by \(p_1\) whilst also being divisible by \(p_2\).

In fact, with the exception of \(p_1 = 3\) and \(p_2 = 5\), for every pair of consecutive primes, \(p_2 > p_1\), there exist values of \(n\) for which the last digits are formed by \(p_1\) and \(n\) is divisible by \(p_2\). Let \(S\) be the smallest of these values of \(n\).

Find \(\displaystyle \sum S\) for every pair of consecutive primes with \(5 \le p_1 \le 1000000\).

Problem 134: Prime Pair Connection

Mathematical Foundation

Theorem 1. Let p1p_1 have dd digits, so 10d1p1<10d10^{d-1} \leq p_1 < 10^d. Then:

S(p1,p2)=p1+k10dS(p_1, p_2) = p_1 + k \cdot 10^d

where k=(p1(10d)1)modp2k = (-p_1 \cdot (10^d)^{-1}) \bmod p_2, and (10d)1(10^d)^{-1} is the modular inverse of 10d10^d modulo p2p_2.

Proof. We seek the smallest positive integer Sp1(mod10d)S \equiv p_1 \pmod{10^d} with p2Sp_2 \mid S. Write S=p1+k10dS = p_1 + k \cdot 10^d for k0k \geq 0. The divisibility condition becomes:

p2(p1+k10d)    k10dp1(modp2)p_2 \mid (p_1 + k \cdot 10^d) \iff k \cdot 10^d \equiv -p_1 \pmod{p_2}

Since p2p_2 is an odd prime greater than 5, gcd(10d,p2)=1\gcd(10^d, p_2) = 1, so the modular inverse exists. Solving: kp1(10d)1(modp2)k \equiv -p_1 \cdot (10^d)^{-1} \pmod{p_2}. Taking the least non-negative residue gives the unique k{0,1,,p21}k \in \{0, 1, \ldots, p_2 - 1\}.

We claim k1k \geq 1. If k=0k = 0, then S=p1S = p_1 and p2p1p_2 \mid p_1. But p2>p1p_2 > p_1 (consecutive primes with p15p_1 \geq 5), so this is impossible. \square

Lemma 1. The modular inverse (10d)1modp2(10^d)^{-1} \bmod p_2 can be computed via Fermat’s little theorem as (10d)p22modp2(10^d)^{p_2 - 2} \bmod p_2, or via the extended Euclidean algorithm.

Proof. By Fermat’s little theorem, ap211(modp2)a^{p_2 - 1} \equiv 1 \pmod{p_2} for gcd(a,p2)=1\gcd(a, p_2) = 1. Hence a1ap22(modp2)a^{-1} \equiv a^{p_2 - 2} \pmod{p_2}. \square

Editorial

For consecutive primes p1, p2 with 5 <= p1 <= 1000003, find S(p1,p2): smallest positive integer ending in p1 and divisible by p2. Sum all S values.

Pseudocode

    primes = sieve_primes(1100000) // slightly above 1000003
    total = 0
    For each i in range where primes[i] >= 5 and primes[i+1] <= 1000003:
        p1 = primes[i]
        p2 = primes[i+1]
        d = number_of_digits(p1)
        pow10 = 10^d
        inv = modular_inverse(pow10, p2) // via extended GCD or Fermat
        k = (-p1 * inv) mod p2
        S = p1 + k * pow10
        total += S
    Return total

Complexity Analysis

  • Time: O(N/lnNlogN)O(N / \ln N \cdot \log N) where N106N \approx 10^6. There are π(106)78,498\pi(10^6) \approx 78{,}498 consecutive pairs, and each modular inverse costs O(logp2)O(\log p_2) via the extended Euclidean algorithm.
  • Space: O(N)O(N) for the prime sieve.

Answer

18613426663617118\boxed{18613426663617118}

Code

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

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

long long power_mod(long long base, long long exp, long long mod) {
    long long result = 1;
    base %= mod;
    while (exp > 0) {
        if (exp & 1) result = (__int128)result * base % mod;
        base = (__int128)base * base % mod;
        exp >>= 1;
    }
    return result;
}

int main() {
    const int LIMIT = 1100000; // need primes a bit above 1000003
    vector<bool> is_prime(LIMIT, true);
    is_prime[0] = is_prime[1] = false;
    for (int i = 2; i * i < LIMIT; i++)
        if (is_prime[i])
            for (int j = i * i; j < LIMIT; j += i)
                is_prime[j] = false;

    vector<int> primes;
    for (int i = 2; i < LIMIT; i++)
        if (is_prime[i])
            primes.push_back(i);

    long long total = 0;

    for (int i = 0; i + 1 < (int)primes.size(); i++) {
        int p1 = primes[i];
        int p2 = primes[i + 1];
        if (p1 < 5) continue;
        if (p1 >= 1000003) break;

        // Number of digits of p1
        long long pow10 = 1;
        int temp = p1;
        while (temp > 0) {
            pow10 *= 10;
            temp /= 10;
        }

        // k = (-p1 * modinv(pow10, p2)) mod p2
        long long inv = power_mod(pow10, p2 - 2, p2);
        long long k = (long long)(-(long long)p1 % p2 + p2) % p2 * inv % p2;

        long long S = p1 + k * pow10;
        total += S;
    }

    cout << total << endl;
    return 0;
}