All Euler problems
Project Euler

Large Non-Mersenne Prime

In 2004, a massive non-Mersenne prime was discovered: N = 28433 x 2^7830457 + 1. Find the last ten digits of N.

Source sync Apr 19, 2026
Problem #0097
Level Level 02
Solved By 47,424
Languages C++, Python
Answer 8739992577
Length 316 words
modular_arithmeticnumber_theoryarithmetic

Problem Statement

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

The first known prime found to exceed one million digits was discovered in 1999, and is a Mersenne prime of the form \(2^{6972593} - 1\); it contains exactly \(2\,098\,960\) digits. Subsequently other Mersenne primes, of the form \(2^p - 1\), have been found which contain more digits.

However, in 2004 there was found a massive non-Mersenne prime which contains \(2\,357\,207\) digits: \(28433 \times 2^{7830457} + 1\).

Find the last ten digits of this prime number.

Problem 97: Large Non-Mersenne Prime

Mathematical Foundation

Theorem 1 (Modular reduction is a ring homomorphism). For any positive integer mm, the canonical projection πm:ZZ/mZ\pi_m : \mathbb{Z} \to \mathbb{Z}/m\mathbb{Z} defined by πm(a)=amodm\pi_m(a) = a \bmod m is a surjective ring homomorphism. In particular, for all a,bZa, b \in \mathbb{Z}:

(a+b)modm=((amodm)+(bmodm))modm,(a + b) \bmod m = ((a \bmod m) + (b \bmod m)) \bmod m, (ab)modm=((amodm)(bmodm))modm.(a \cdot b) \bmod m = ((a \bmod m) \cdot (b \bmod m)) \bmod m.

Proof. Write a=q1m+r1a = q_1 m + r_1 and b=q2m+r2b = q_2 m + r_2 with 0r1,r2<m0 \le r_1, r_2 < m. Then a+b=(q1+q2)m+(r1+r2)a + b = (q_1 + q_2)m + (r_1 + r_2), so (a+b)modm=(r1+r2)modm(a+b) \bmod m = (r_1 + r_2) \bmod m. Similarly, ab=(q1q2m+q1r2+q2r1)m+r1r2ab = (q_1 q_2 m + q_1 r_2 + q_2 r_1)m + r_1 r_2, so (ab)modm=(r1r2)modm(ab) \bmod m = (r_1 r_2) \bmod m. These are precisely the ring axioms for Z/mZ\mathbb{Z}/m\mathbb{Z}. \square

Corollary 1. For any a,c,mZa, c, m \in \mathbb{Z} with m>0m > 0:

(cae+1)modm=(c(aemodm)+1)modm.(c \cdot a^e + 1) \bmod m = (c \cdot (a^e \bmod m) + 1) \bmod m.

Theorem 2 (Correctness of binary exponentiation). Let b,e,mb, e, m be positive integers with binary representation e=i=0kei2ie = \sum_{i=0}^{k} e_i 2^i. The following procedure computes bemodmb^e \bmod m:

Initialize r1r \leftarrow 1, gbmodmg \leftarrow b \bmod m. For i=0,1,,ki = 0, 1, \ldots, k: if ei=1e_i = 1, set r(rg)modmr \leftarrow (r \cdot g) \bmod m; then set gg2modmg \leftarrow g^2 \bmod m.

Proof. We prove by induction on ii that after iteration ii, rbj=0iej2j(modm)r \equiv b^{\sum_{j=0}^{i} e_j 2^j} \pmod{m} and gb2i+1(modm)g \equiv b^{2^{i+1}} \pmod{m}.

Base case (i=1i = -1, before the loop): r=1=b0r = 1 = b^0 and g=b1modmg = b^1 \bmod m. Both invariants hold.

Inductive step: Suppose the invariants hold before iteration ii. We have gb2i(modm)g \equiv b^{2^i} \pmod{m} (by the invariant from iteration i1i-1). If ei=1e_i = 1, then rrgbj<iej2jb2i=bjiej2j(modm)r \leftarrow r \cdot g \equiv b^{\sum_{j<i} e_j 2^j} \cdot b^{2^i} = b^{\sum_{j \le i} e_j 2^j} \pmod{m} by Theorem 1. If ei=0e_i = 0, rr is unchanged and jiej2j=j<iej2j\sum_{j \le i} e_j 2^j = \sum_{j < i} e_j 2^j. Then gg2b2i+1(modm)g \leftarrow g^2 \equiv b^{2^{i+1}} \pmod{m}.

After all k+1k+1 iterations, rbi=0kei2i=be(modm)r \equiv b^{\sum_{i=0}^{k} e_i 2^i} = b^e \pmod{m}. \square

Theorem 3 (Bit-complexity). Binary exponentiation of bemodmb^e \bmod m performs log2e+1\lfloor \log_2 e \rfloor + 1 squarings and at most log2e+1\lfloor \log_2 e \rfloor + 1 multiplications, each modulo mm. If mm fits in a machine word, each modular multiplication is O(1)O(1), giving total time O(loge)O(\log e).

Proof. The loop iterates once per bit of ee, performing one squaring and at most one multiplication per iteration. \square

Application. With m=1010m = 10^{10}, b=2b = 2, and e=7830457e = 7830457:

Nmod1010=(28433(27830457mod1010)+1)mod1010.N \bmod 10^{10} = (28433 \cdot (2^{7830457} \bmod 10^{10}) + 1) \bmod 10^{10}.

The exponent e=7830457e = 7830457 has log27830457+1=23\lfloor \log_2 7830457 \rfloor + 1 = 23 bits, so the computation requires 23 squarings and at most 23 multiplications modulo 101010^{10}. Since 1010<23410^{10} < 2^{34}, all intermediate products fit in 64-bit arithmetic (using 128-bit intermediate results for the multiplication step).

Editorial

Only the last ten digits matter, so every operation can be performed modulo 101010^{10}. That means we never need to build the enormous number 278304572^{7830457} itself; we only need its residue modulo the target modulus.

The heavy step is modular exponentiation, and repeated squaring handles that in logarithmic time. After computing 27830457mod10102^{7830457} \bmod 10^{10}, the remaining multiplication by 2843328433 and the final addition of 11 are done under the same modulus. The search space is therefore reduced from a huge integer to a short sequence of modular updates.

Pseudocode

Set the modulus to $10^{10}$.

Compute the residue of $2^{7830457}$ modulo this modulus.
Multiply that residue by $28433$.
Add $1$ and reduce once more modulo $10^{10}$.

Return the resulting last ten digits.

Complexity Analysis

Time: O(loge)=O(23)O(\log e) = O(23) modular multiplications. Each is O(1)O(1) with fixed-precision arithmetic. Total: O(1)O(1).

Space: O(1)O(1).

Answer

8739992577\boxed{8739992577}

Code

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

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

int main() {
    // Compute (28433 * 2^7830457 + 1) mod 10^10
    // Using binary exponentiation with __int128 to avoid overflow.

    const long long mod = 10000000000LL;

    auto mulmod = [](long long a, long long b, long long m) -> long long {
        return ((__int128)a * b) % m;
    };

    // Binary exponentiation: 2^7830457 mod 10^10
    long long base = 2, exp = 7830457, result = 1;
    base %= mod;
    while (exp > 0) {
        if (exp & 1)
            result = mulmod(result, base, mod);
        base = mulmod(base, base, mod);
        exp >>= 1;
    }

    result = mulmod(28433LL, result, mod);
    result = (result + 1) % mod;

    cout << result << endl;
    return 0;
}