Problem 46 — Goldbach's Other Conjecture

solved Wed, 4 Dec 2019, 15:25 · level 1 · difficulty 5% projecteuler.net github

It was proposed by Christian Goldbach that every odd composite number can be written as the sum of a prime and twice a square.

$$\begin{align} 9 = 7 + 2 \times 1^2\\ 15 = 7 + 2 \times 2^2\\ 21 = 3 + 2 \times 3^2\\ 25 = 7 + 2 \times 3^2\\ 27 = 19 + 2 \times 2^2\\ 33 = 31 + 2 \times 1^2 \end{align}$$

It turns out that the conjecture was false.

What is the smallest odd composite that cannot be written as the sum of a prime and twice a square?


Problem Analysis

Christian Goldbach's "other" conjecture asserts that every odd composite number can be written as the sum of a prime and twice a perfect square, that is n = p + 2k2 for some prime p and integer k >= 1. A composite number is one with divisors other than 1 and itself - in other words, not prime. The conjecture is false, and my task is to find the smallest counterexample: the first odd composite for which no such decomposition exists.

The natural way to disprove a universal statement is to hunt for a counterexample by enumeration. I walk the integers upward, classify each as prime or composite, and for every odd composite I test exhaustively whether some valid (p, k) pair exists. Two observations keep the cost low. First, I only ever examine odd composites - even numbers and primes are skipped at once. Second, for a fixed candidate n, rather than iterating over all possible squares I iterate over the primes p below n and ask whether (n - p) / 2 is a perfect square - a constant-time test using a square root. Each candidate therefore costs O(pi(n)) work, where pi(n) counts the primes below n. By the prime number theorem, pi(n) is about n / ln n, so the entire search up to the answer N = 5777 runs in roughly O(N2 / ln N) time - trivially fast at this scale.

Solution Approach

Approach 0 - Enumerate and Test the Conjecture (Python and C)

Both files implement the same overall algorithm: iterate over integers from 2 upward, decide primality, accumulate the primes found so far, and for each odd composite test the conjecture by searching the known primes for a decomposition. The only real difference is how primality is decided.

The Python solution uses an incremental sieve of Eratosthenes. A dictionary known_composites maps each future composite number to the list of primes that will reach it. When the current number is absent from the dictionary, no recorded prime factor reaches it, so it must be prime: I add it to the primes set and register its square as the first composite it generates. When the current number is present, it is composite; I advance each of its prime factors p forward to the next multiple p + current_number, then delete the consumed entry. For odd composites I run the conjecture check before advancing the sieve.

The conjecture check is the heart of the algorithm. For an odd composite n, the code asks any((((current_number - p) / 2) ** 0.5 % 1 == 0 for p in primes if current_number > p != 2)). For each prime p strictly below n (excluding 2, since n - 2 would be odd and not divisible by 2), it computes (n - p) / 2 and tests whether its square root is integral by checking that the fractional part is zero. If no prime yields a perfect square, the candidate is returned as the answer.

The C solution decides primality by trial division against the primes found so far, dividing only by primes up to the square root of the candidate. This is correct because any composite must have a prime factor no larger than its square root. The primes live in a dynamic array that doubles in capacity when full. For odd composites the inner loop mirrors the Python check, but in pure integer arithmetic: it computes half = (current - p) / 2, takes root = (int)sqrt((double)half), and confirms root * root == half. This integer confirmation is robust against floating-point rounding, although both are exact at this scale.

workbench

Test cases

categoryinputanswer
main 5777

Results

solutioncategoryanswerverdict avg seconds cavg seconds py
p0046_s0 main 5777 correct 0.000252 (63) 0.017575 (63)

Files

Tags & blogs

Blogs