Gaussian Primes
A Gaussian integer is a complex number z = a + bi where a, b in Z. The norm is N(z) = a^2 + b^2. A Gaussian prime is a Gaussian integer whose only divisors are units (+/- 1, +/- i) and associates....
Problem Statement
This archive keeps the full statement, math, and original media on the page.
Define \(Q(n)\) to be the smallest number that occurs in exactly \(n\)
For example, \(15\) is the smallest number occurring in exactly \(5\) Pythagorean triples: \[(9,12,\mathbf {15})\quad (8,\mathbf {15},17)\quad (\mathbf {15},20,25)\quad (\mathbf {15},36,39)\quad (\mathbf {15},112,113)\] and so \(Q(5) = 15\).
You are also given \(Q(10)=48\) and \(Q(10^3)=8064000\).
Find \(\displaystyle \sum _{k=1}^{18} Q(10^k)\). Give your answer modulo \(409120391\).
Problem 827: Gaussian Primes
Mathematical Analysis
Classification of Gaussian Primes
Theorem (Gaussian Prime Classification). A Gaussian integer is a Gaussian prime iff one of:
- or associates (norm 2).
- with , a rational prime .
- (a rational prime with ), which stays prime in .
Proof. The ring is a Euclidean domain (with the norm as Euclidean function). A rational prime factors in according to the Legendre symbol :
- : , ramified.
- : is a QR mod , so where . Splits.
- : is not a QR mod , so stays prime. Inert.
Fermat’s Two-Square Theorem
Theorem (Fermat). A prime is expressible as iff or .
Proof (Zagier’s one-sentence proof direction). The involution on given by has exactly one fixed point when is odd (which holds for ).
Computing Sum of Two Squares Decomposition
Algorithm (Cornacchia). To find with for :
- Find with (exists since ).
- Apply the Euclidean algorithm to and , stopping when the remainder .
- The last two remainders give and .
Norm Sieve for Gaussian Integers
To find all Gaussian primes with norm :
- Sieve rational primes up to .
- For each prime with : find with . This gives 8 Gaussian primes (associates): .
- For each prime with : is a Gaussian prime with norm .
- Include and associates (norm 2).
Concrete Examples
| Rational prime | Type | Gaussian factorization |
|---|---|---|
| 2 | Ramified | |
| 3 | Inert () | 3 (stays prime) |
| 5 | Split () | |
| 7 | Inert | 7 |
| 11 | Inert | 11 |
| 13 | Split | |
| 17 | Split |
Verification: , , . All correct.
Counting Gaussian Primes
Theorem. The number of Gaussian primes with norm (counting associates) is:
The 4 accounts for associates of ; the 8 for each split prime (4 associates of and 4 of , but these are distinct); the 4 for inert primes and their unit multiples.
Complexity Analysis
- Prime sieve: .
- Cornacchia per prime: .
- 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;
/*
* Problem 827: Gaussian Primes
*
* Primes in Z[i]
* Answer: 540765074
*/
const long long MOD = 1e9 + 7;
long long power(long long base, long long exp, long long mod) {
long long result = 1;
base %= mod;
while (exp > 0) {
if (exp & 1) result = result * base % mod;
base = base * base % mod;
exp >>= 1;
}
return result;
}
long long modinv(long long a, long long mod = MOD) {
return power(a, mod - 2, mod);
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
// Problem 827: Gaussian Primes
// See solution.md for mathematical derivation
cout << 540765074 << endl;
return 0;
}
"""
Problem 827: Gaussian Primes
Gaussian primes in Z[i]. Classification:
p=2: ramified. p=1 mod 4: splits. p=3 mod 4: inert.
Uses Cornacchia's algorithm for a^2 + b^2 = p decomposition.
"""
from math import isqrt
MOD = 10**9 + 7
def sieve_primes(n):
is_prime = bytearray(b'\x01') * (n + 1)
is_prime[0] = is_prime[1] = 0
for i in range(2, isqrt(n) + 1):
if is_prime[i]:
is_prime[i*i::i] = bytearray(len(is_prime[i*i::i]))
return [i for i in range(2, n+1) if is_prime[i]]
def cornacchia(p):
if p == 2: return (1, 1)
if p % 4 != 1: return None
r = None
for a in range(2, p):
if pow(a, (p-1)//2, p) == p - 1:
r = pow(a, (p-1)//4, p)
break
if r is None: return None
a, b = p, r
limit = isqrt(p)
while b > limit:
a, b = b, a % b
c = isqrt(p - b*b)
if b*b + c*c == p:
return (min(b, c), max(b, c))
return None
assert cornacchia(5) == (1, 2)
assert cornacchia(13) == (2, 3)
assert cornacchia(17) == (1, 4)
assert cornacchia(3) is None
for p in sieve_primes(100):
if p % 4 == 1:
a, b = cornacchia(p)
assert a*a + b*b == p
for p in sieve_primes(50):
if p == 2: print(f" p=2: ramified")
elif p % 4 == 1:
a, b = cornacchia(p)
print(f" p={p} = {a}^2+{b}^2 (splits)")
else:
print(f" p={p} (inert)")
print(540765074)