Goldbach's Conjecture_POJ 2262

题目

题目链接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: 
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.

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值