欧拉筛预处理素数表,每次询问贪心取最小的奇素数 a,并 O(1) 判断 n - a 是否为素数。
OJ: roj
题目 ID: 1622
难度:普及-
标签:数论素数筛法贪心
创建: 2026-09-30 22:31
更新: 2026-10-06 01:19
题目描述
哥德巴赫猜想:任何大于 Goldbach's conjecture is wrong.。数据范围 8、20、42 各一行并以 0 结束,输出为 8 = 3 + 5、20 = 3 + 17、42 = 5 + 37。
思路
因为
参考代码
Python 版:
python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-09-30 22:32
# update_at: 2026-09-30 22:32
import sys
MAX_V = 1_000_000
def build_sieve(limit: int) -> tuple[bytearray, list[int]]:
"""欧拉筛预处理素数表与质数判定表。"""
is_prime = bytearray([1]) * (limit + 1)
is_prime[0] = is_prime[1] = 0
primes: list[int] = []
for i in range(2, limit + 1):
if is_prime[i]:
primes.append(i)
for p in primes:
if i * p > limit:
break
is_prime[i * p] = 0
if i % p == 0:
break
return is_prime, primes
def find_goldbach_pair(n: int, primes: list[int], is_prime: bytearray) -> tuple[int, int] | None:
"""寻找使得 n = a + b 且 b - a 最大的奇素数对 (a, b)。"""
for p in primes:
if p > n // 2:
break
if p == 2:
continue
q = n - p
if is_prime[q]:
return p, q
return None
def solve() -> None:
input_data = sys.stdin.buffer.read().split()
if not input_data:
return
is_prime, primes = build_sieve(MAX_V)
out: list[str] = []
for token in input_data:
n = int(token)
if n == 0:
break
pair = find_goldbach_pair(n, primes, is_prime)
if pair:
a, b = pair
out.append(f"{n} = {a} + {b}")
else:
out.append("Goldbach's conjecture is wrong.")
sys.stdout.write("\n".join(out) + "\n")
if __name__ == "__main__":
solve()C++ 版(同一算法):
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-10-06 01:18
* update_at: 2026-10-06 01:18
*/
// roj 1622 Goldbach's Conjecture:欧拉筛预处理素数表,逐组贪心取最小奇素数 a。
#include <iostream>
#include <vector>
typedef long long ll;
const int MAXN = 1000000; // 题面保证 6 <= n <= 10^6
bool is_prime[MAXN + 1]; // is_prime[x] 表示 x 是否为素数
std::vector<int> primes; // 按升序保存 [2, MAXN] 内的所有素数
// 欧拉筛:O(MAXN) 预处理素数表与素数判定表。
void build_sieve() {
for (int i = 0; i <= MAXN; i++) {
is_prime[i] = true;
}
is_prime[0] = false;
is_prime[1] = false;
for (int i = 2; i <= MAXN; i++) {
if (is_prime[i]) {
primes.push_back(i);
}
for (int j = 0; j < (int)primes.size(); j++) {
ll product = (ll)i * primes[j];
if (product > MAXN) {
break;
}
is_prime[product] = false;
if (i % primes[j] == 0) {
break;
}
}
}
}
int main() {
build_sieve();
ll n;
while (std::cin >> n) {
if (n == 0) {
break;
}
// b - a = n - 2a 随 a 增大而减小,故取最小的奇素数 a 即为最优解。
bool found = false;
for (int i = 0; i < (int)primes.size(); i++) {
ll a = primes[i];
if (a > n / 2) {
break;
}
if (a == 2) {
continue; // 只取奇素数,2 留给其他分解
}
ll b = n - a;
if (is_prime[b]) {
std::cout << n << " = " << a << " + " << b << "\n";
found = true;
break;
}
}
if (!found) {
std::cout << "Goldbach's conjecture is wrong.\n";
}
}
return 0;
}