Consecutive Prime Sum
Which prime, below one million, can be written as the sum of the most consecutive primes?
Problem Statement
This archive keeps the full statement, math, and original media on the page.
>The prime \(41\), can be written as the sum of six consecutive primes: \[41 = 2 + 3 + 5 + 7 + 11 + 13.\] This is the longest sum of consecutive primes that adds to a prime below one-hundred.
The longest sum of consecutive primes below one-thousand that adds to a prime, contains \(21\) terms, and is equal to \(953\).
Which prime, below one-million, can be written as the sum of the most consecutive primes?
Problem 50: Consecutive Prime Sum
Mathematical Development
Formal Development
Definition 1 (Consecutive prime sum). Let denote the primes in ascending order. A consecutive prime sum of length starting at index is:
We seek the prime such that for some and , with maximized.
Theorem 1 (Prefix sum formulation). Define and for . Then , and each evaluation is after preprocessing.
Proof. By telescoping:
The prefix sums are computed in a single pass in time.
Lemma 1 (Maximum feasible length). Define . No consecutive prime sum of length exceeding can be less than .
Proof. The sum uses the smallest primes, so for all (since is non-decreasing in , replacing by for can only increase the sum). Therefore, if , then for all , so no chain of length sums to a prime below .
Theorem 2 (Optimal search strategy). The following algorithm correctly finds the prime below that is the longest consecutive prime sum:
- Compute as in Lemma 1.
- For : for each starting index with , test whether is prime.
- Return the first prime found.
Proof of correctness. The search proceeds in order of decreasing . For a given , if any is prime (and ), it is optimal among all chains of that exact length (we only need one). Since we try the largest first, the first prime found has maximal length. By Lemma 1, no chain longer than exists, so the search space is complete.
Proof of termination. For , every starting prime is itself a valid consecutive prime sum of length 1, so the algorithm always terminates.
Theorem 3. The prime below expressible as the longest consecutive prime sum is . It equals the sum of consecutive primes starting from :
Proof. We apply the Sieve of Eratosthenes to generate all primes below (there are such primes). Prefix sums are computed per Theorem 1. The search of Theorem 2 finds:
- (since and ).
- For : no starting index yields a prime sum below .
- For : starting at (i.e., ), .
Primality verification. is confirmed prime by the sieve (alternatively, , and trial division by all primes up to yields no factor).
Optimality. No chain of length or yields a prime below , and is the first length for which a prime is found.
Editorial
We sieve all primes below the limit and build prefix sums of the prime sequence, which makes every consecutive prime sum a constant-time difference of two prefixes. Candidate chain lengths are then examined in decreasing order; for each length, the starting index is advanced until the corresponding sum reaches the limit, and primality is checked by table lookup. Because the search proceeds from longer chains to shorter ones, the first prime found is the optimal answer.
Pseudocode
Algorithm: Prime Below the Limit Expressible as the Longest Consecutive Prime Sum
Require: A prime bound L.
Ensure: The prime below L that can be written as the sum of the longest run of consecutive primes.
1: Sieve all primes below L and form the prime sequence p_0, p_1, ... together with prefix sums P_m.
2: For candidate lengths ell, examined from longest to shortest, do:
3: For each admissible start index s, compute X ← P_(s + ell) - P_s.
4: If X < L and X is prime, return X.
Complexity Analysis
Proposition (Time complexity). The algorithm runs in worst-case time, but with early termination, the practical complexity is much smaller.
Proof. The sieve costs . Prefix sum computation is . The nested search loop iterates over lengths from downward. For each length , the inner loop runs at most iterations, each costing (sieve lookup). In the worst case, this gives .
However, with early termination (stopping as soon as the first prime is found for any length , and breaking when drops to best_len), the practical runtime is dominated by the sieve. For , the search terminates after examining only a few lengths near .
Proposition (Space complexity). for the sieve, plus for the prime list and prefix sums. Total: .
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#include <bits/stdc++.h>
using namespace std;
int main() {
const int LIMIT = 1000000;
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);
int n = primes.size();
vector<long long> prefix(n + 1, 0);
for (int i = 0; i < n; i++)
prefix[i + 1] = prefix[i] + primes[i];
int best_len = 0;
int best_prime = 0;
for (int len = n; len > best_len; len--) {
for (int start = 0; start + len <= n; start++) {
long long s = prefix[start + len] - prefix[start];
if (s >= LIMIT) break;
if (is_prime[(int)s]) {
best_len = len;
best_prime = (int)s;
break;
}
}
}
cout << best_prime << endl;
return 0;
}
"""
Problem 50: Consecutive Prime Sum
Which prime below one million can be written as the sum of the most
consecutive primes?
"""
def solve():
LIMIT = 1_000_000
is_prime = [True] * LIMIT
is_prime[0] = is_prime[1] = False
for i in range(2, int(LIMIT**0.5) + 1):
if is_prime[i]:
for j in range(i * i, LIMIT, i):
is_prime[j] = False
primes = [i for i in range(2, LIMIT) if is_prime[i]]
n = len(primes)
prefix = [0] * (n + 1)
for i in range(n):
prefix[i + 1] = prefix[i] + primes[i]
best_len = 0
best_prime = 0
for length in range(n, best_len, -1):
for start in range(n - length + 1):
s = prefix[start + length] - prefix[start]
if s >= LIMIT:
break
if is_prime[s]:
best_len = length
best_prime = s
break
if best_len == length:
break
return best_prime
answer = solve()
assert answer == 997651
print(answer)