All Euler problems
Project Euler

Quadratic Primes

Considering quadratics of the form n^2 + an + b where |a| < 1000 and |b| <= 1000, find the product of the coefficients a and b that produces the maximum number of primes for consecutive values of n...

Source sync Apr 19, 2026
Problem #0027
Level Level 01
Solved By 96,714
Languages C++, Python
Answer -59231
Length 519 words
number_theoryalgebramodular_arithmetic

Problem Statement

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

Euler discovered the remarkable quadratic formula: \[n^2 + n + 41\] It turns out that the formula will produce \(40\) primes for the consecutive integer values \(0 \le n \le 39\). However, when \(n = 40, 40^2 + 40 + 41 = 40(40 + 1) + 41\) is divisible by \(41\), and certainly when \(n = 41, 41^2 + 41 + 41\) is clearly divisible by \(41\).

The incredible formula \(n^2 - 79n + 1601\) was discovered, which produces \(80\) primes for the consecutive values \(0 \le n \le 79\). The product of the coefficients, \(-79\) and \(1601\), is \(-126479\).

Considering quadratics of the form:

\(n^2 + an + b\), where \(|a| < 1000\) and \(|b| \le 1000\)

where \(|n|\) is the modulus/absolute value of \(n\)

e.g. \(|11| = 11\) and \(|-4| = 4\)

Find the product of the coefficients, \(a\) and \(b\), for the quadratic expression that produces the maximum number of primes for consecutive values of \(n\), starting with \(n = 0\).

Problem 27: Quadratic Primes

Mathematical Development

Definition 1. For integers a,ba, b, define fa,b(n)=n2+an+bf_{a,b}(n) = n^2 + an + b. The prime chain length of (a,b)(a, b) is L(a,b)=max{m0:fa,b(n) is prime for all 0n<m}L(a, b) = \max\{m \geq 0 : f_{a,b}(n) \text{ is prime for all } 0 \leq n < m\}.

Lemma 1 (Necessity of bb Prime). If L(a,b)1L(a, b) \geq 1, then bb is a positive prime.

Proof. Evaluating at n=0n = 0 gives fa,b(0)=bf_{a,b}(0) = b. For bb to be prime, we need b2b \geq 2. \square

Lemma 2 (Parity Constraint). If bb is an odd prime and L(a,b)2L(a, b) \geq 2, then aa is odd.

Proof. We require fa,b(1)=1+a+bf_{a,b}(1) = 1 + a + b to be prime. Since bb is odd, 1+a+b1 + a + b has the same parity as aa. If aa is even, then 1+a+b1 + a + b is even, so fa,b(1)=2f_{a,b}(1) = 2 is the only possibility, forcing a=1ba = 1 - b. But then fa,b(2)=4+2(1b)+b=6b<2f_{a,b}(2) = 4 + 2(1-b) + b = 6 - b < 2 for b5b \geq 5, contradicting L(a,b)2L(a,b) \geq 2. For b=3b = 3: a=2a = -2, f(2)=44+3=3f(2) = 4 - 4 + 3 = 3 (prime), f(3)=96+3=6f(3) = 9 - 6 + 3 = 6 (not prime), giving L=3L = 3. This is a short chain. For long chains with b5b \geq 5, we need aa odd. \square

Lemma 3 (Lower Bound on aa). If L(a,b)2L(a, b) \geq 2, then a>ba > -b.

Proof. We need fa,b(1)=1+a+b2f_{a,b}(1) = 1 + a + b \geq 2, so a1ba \geq 1 - b, i.e., a>ba > -b. \square

Theorem 1 (Connection to Heegner Numbers). Euler’s quadratic n2+n+41n^2 + n + 41 produces primes for n=0,1,,39n = 0, 1, \ldots, 39. This is intimately connected to the fact that 163-163 is a Heegner number.

Proof. The discriminant of n2+n+41n^2 + n + 41 is Δ=12441=163\Delta = 1^2 - 4 \cdot 41 = -163. By the Stark—Heegner theorem, the imaginary quadratic field Q(163)\mathbb{Q}(\sqrt{-163}) has class number h(163)=1h(-163) = 1, meaning its ring of integers Z[1+1632]\mathbb{Z}\bigl[\frac{1+\sqrt{-163}}{2}\bigr] is a principal ideal domain (and hence a unique factorization domain). In the theory of binary quadratic forms, class number 1 implies that the principal form x2+xy+41y2x^2 + xy + 41y^2 is the unique reduced form of discriminant 163-163. By Rabinowitz’s theorem (1913), a quadratic n2+n+pn^2 + n + p produces primes for n=0,1,,p2n = 0, 1, \ldots, p - 2 if and only if the class number h(14p)=1h(1 - 4p) = 1. Since h(163)=1h(-163) = 1 and p=41p = 41, the quadratic n2+n+41n^2 + n + 41 is prime for n=0,,39n = 0, \ldots, 39. \square

Remark. The quadratic n279n+1601=(n40)2+(n40)+41n^2 - 79n + 1601 = (n - 40)^2 + (n - 40) + 41 is a reindexing of Euler’s polynomial, producing 80 primes for n=0,,79n = 0, \ldots, 79.

Theorem 2 (Optimal Coefficients). Among all (a,b)(a, b) with a<1000|a| < 1000 and b1000|b| \leq 1000, the pair maximizing L(a,b)L(a, b) is (a,b)=(61,971)(a, b) = (-61, 971), with L(61,971)=71L(-61, 971) = 71. The product is ab=59231a \cdot b = -59231.

Proof. By exhaustive search. The search space is constrained as follows:

  1. By Lemma 1, bb ranges over the 168 primes in [2,1000][2, 1000].
  2. By Lemma 2, for odd b5b \geq 5, only odd values of aa are tested.
  3. By Lemma 3, a>ba > -b.

For each admissible (a,b)(a, b), we evaluate fa,b(n)f_{a,b}(n) for n=0,1,2,n = 0, 1, 2, \ldots until a composite or negative value is reached. Primality is checked via a precomputed sieve. The maximum chain length found is 7171, achieved uniquely at (a,b)=(61,971)(a, b) = (-61, 971). The discriminant of n261n+971n^2 - 61n + 971 is 6124971=37213884=16361^2 - 4 \cdot 971 = 3721 - 3884 = -163, confirming the connection to the Heegner number 163-163. \square

Editorial

We search over the admissible coefficient pairs using number-theoretic pruning. Because f(0)=bf(0) = b must be prime, we only enumerate prime values of bb, precompute a prime sieve large enough for all tested values, and then scan the allowed range of aa while skipping parity patterns that cannot produce long prime runs. For each pair (a,b)(a, b) we count consecutive values of nn starting from 0 until n2+an+bn^2 + an + b stops being prime, and we keep the product abab for the longest run. This is sufficient because every candidate pair in the search region is either tested or eliminated by a necessary condition.

Pseudocode

Algorithm: Quadratic Polynomial Producing the Longest Prime Run
Require: Bounds A and B for the coefficients.
Ensure: The product ab for the coefficient pair maximizing the number of consecutive prime values of n^2 + an + b starting at n = 0.
1: Build a prime table large enough for all values tested, and enumerate the admissible prime values of b.
2: Initialize best_run ← 0 and best_pair ← (0, 0).
3: For each candidate pair (a, b) with |a| < A and prime b ≤ B, count the consecutive integers n ≥ 0 for which n^2 + an + b is positive and prime.
4: If this count exceeds best_run, update best_run ← count and best_pair ← (a, b).
5: Return the product of the two entries of best_pair.

Complexity Analysis

Proposition (Time Complexity). The algorithm runs in O(BAC)O(|B| \cdot |A| \cdot C) time, where B=π(Bmax)=168|B| = \pi(B_{\max}) = 168 is the number of candidate primes, A2Amax=1998|A| \leq 2A_{\max} = 1998 is the range of aa (halved by parity pruning for odd bb), and C71C \leq 71 is the maximum chain length. Total: O(168×1000×71)1.2×107O(168 \times 1000 \times 71) \approx 1.2 \times 10^7 operations.

Proof. The outer loops enumerate at most BA|B| \cdot |A| pairs. For each pair, the inner loop runs at most CC iterations, each performing an O(1)O(1) sieve lookup. \square

Proposition (Space Complexity). The algorithm uses O(S)O(S) space where S=O(Amax2)S = O(A_{\max}^2) is the sieve size. We need to test values up to approximately 702+99970+1000=7583070^2 + 999 \cdot 70 + 1000 = 75830, so S105S \approx 10^5.

Answer

59231\boxed{-59231}

Code

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

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

int main() {
    const int LIMIT = 1000000;
    vector<bool> is_prime(LIMIT + 1, 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;

    auto check_prime = [&](int n) -> bool {
        if (n < 2) return false;
        if (n <= LIMIT) return is_prime[n];
        for (int i = 2; (long long)i * i <= n; i++)
            if (n % i == 0) return false;
        return true;
    };

    int best_a = 0, best_b = 0, best_count = 0;

    for (int b = 2; b <= 1000; b++) {
        if (!is_prime[b]) continue;
        for (int a = -999; a < 1000; a++) {
            int n = 0;
            while (check_prime(n * n + a * n + b))
                n++;
            if (n > best_count) {
                best_count = n;
                best_a = a;
                best_b = b;
            }
        }
    }

    cout << (long long)best_a * best_b << endl;
    return 0;
}