题目
题目链接http://poj.org/problem?id=2262
Goldbach's Conjecture
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 45238 | Accepted: 17237 |
Description
In 1742, Christian Goldbach, a German amateur mathematician, sent a letter to Leonhard Euler in which he made the following conjecture:
For example:
Today it is still unproven whether the conjecture is right. (Oh wait, I have the proof of course, but it is too long to write it on the margin of this page.)
Anyway, your task is now to verify Goldbach's conjecture for all even numbers less than a million.
Every even number greater than 4 can be
written as the sum of two odd prime numbers.
For example:
8 = 3 + 5. Both 3 and 5 are odd prime numbers.
20 = 3 + 17 = 7 + 13.
42 = 5 + 37 = 11 + 31 = 13 + 29 = 19 + 23.
Today it is still unproven whether the conjecture is right. (Oh wait, I have the proof of course, but it is too long to write it on the margin of this page.)
Anyway, your task is now to verify Goldbach's conjecture for all even numbers less than a million.
Input
The input will contain one or more test cases.
Each test case consists of one even integer n with 6 <= n < 1000000.
Input will be terminated by a value of 0 for n.
Each test case consists of one even integer n with 6 <= n < 1000000.
Input will be terminated by a value of 0 for n.
Output
For each test case, print one line of the form n = a + b, where a and b are odd primes. Numbers and operators should be separated by exactly one blank like in the sample output below. If there is more than one pair of odd primes adding up to n, choose the pair where the difference b - a is maximized. If there is no such pair, print a line saying "Goldbach's conjecture is wrong."
Sample Input
8 20 42 0
Sample Output
8 = 3 + 5 20 = 3 + 17 42 = 5 + 37
Source
思路
1. 素数判定。判断是否存在两个和为 n 的素数。
2. 素数判定有O(n^-2)的朴素素数测试法,和O(n*lglgn)的文氏筛法,这里采用的是文氏筛法。
1. 看着n <= 10^6, 本想着节约空间,就没采用数组保存素数,用的set,结果TLE,实在想不出还能怎么优化。。。最后看的大神们的题解,才知道自己用set保存素数,查找操作是Omega(lgn),所以总的复杂度是O(nlgn),10^6本来就有点悬。(想不通直接素数判定的O(n*n^-2)都能过。。难道是我算错复杂度了)。。。而用数组保存的话,查找操作O(1),总的复杂度是O(n),算是空间换时间。
2. 这道题收货就是,要学会估算复杂度,数据结构要选择合适。。。
代码
这是我
set保存的代码,提交后TLE
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
#define MAX_N 1000000
vector<int> data;
set<int> prime;
bool is_prime[MAX_N+1];
void prime_sieve(int n);
int main()
{
//#define LOCAL
#ifdef LOCAL
freopen("data.in", "r", stdin);
#endif // LOCAL
int N;
int largest = 0;
set<int>::iterator it;
vector<int>::iterator it_data;
while ( scanf("%d", &N) && N != 0) {
data.push_back(N);
largest = max(largest, N);
}
prime_sieve(largest+100);
int da;
for (it_data = data.begin(); it_data != data.end(); it_data++) {
da = *it_data;
it = prime.lower_bound(da); // O(nlgn)
for ( ; *it >= da/2; it--) {
if (binary_search(prime.begin(), prime.end(), da-(*it))) {
printf("%d = %d + %d\n", da, da - (*it), (*it) );
break;
}
}
if (*it < da/2) {
cout << "Goldbach's conjecture is wrong." << endl;
}
}
return 0;
}
void prime_sieve(int n) {
for (int i = 0; i <= n; i++) is_prime[i] = true;
is_prime[0] = is_prime[1] = false;
for (int i = 2; i <= n; i++) {
if (is_prime[i]) {
prime.insert(i);
for (int j = 2*i; j <= n; j += i) is_prime[j] = false;
}
}
}
这是我参照别人题解写的,复杂度 O(n)
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
#define MAX_N 1000000
int prime[MAX_N+100];
bool is_prime[MAX_N+100];
ll prime_sieve(ll n);
int main()
{
//#define LOCAL
#ifdef LOCAL
freopen("data.in", "r", stdin);
#endif // LOCAL
ll N;
prime_sieve(MAX_N+10);
while ( scanf("%lld", &N) && N != 0) {
ll i;
for (i = N-1; i >= N/2; i--) { //复杂度 O(n)
if (is_prime[i] && is_prime[N-i]) {
printf("%lld = %lld + %lld\n", N, N-i, i);
break;
}
}
if (i < N/2) cout << "Goldbach's conjecture is wrong." << endl;
}
return 0;
}
ll prime_sieve(ll n) {
ll p = 0;
for (ll i = 0; i <= n; i++) is_prime[i] = true;
is_prime[0] = is_prime[1] = false;
for (ll i = 2; i <= n; i++) {
if (is_prime[i]) {
prime[p++] = i;
for (ll j = 2*i; j <= n; j += i) is_prime[j] = false;
}
}
return p;
}