2262:Goldbach's Conjecture:埃及筛法+尺取 证明哥德巴赫猜想

题目大意

题目链接
哥德巴赫猜想:任何大于 4 的偶数都可以拆成两 个奇素数之和。

比如: 8=3+5

20=3+17=7+13

42=5+37=11+31=13+29=19+23

你的任务是:验证小于10^6的数满足哥德巴赫猜想。

输出格式

对于每组数据,输出形如 n=a+b,其中 a,b 是奇素数。

若有多组满足条件的 a,b,输出 b−a 最大的一组。若无解,输出 Goldbach’s conjecture is wrong.(注意有句号)。

思路分析

看了很多题解都是打表+枚举,感觉有点憨憨的,要写还是尽自己所能吧,首先打表很容游戏想到,埃及筛法了解一下。因为素数的个数是固定的,我们一次把他们全部取出来放到一个单独的item数组中,而不是遍历所有的数字。1000000中大概有80000左右的odd prime,一下复杂度就/10了,此时如果prime比较少,我们依然可以打表,记录所有可能的两个odd prime的组合,后面直接输出,可惜这里太大,还是得依次处理,主要有两个优化

  • 每次我们在item数组中找到第一个大于n/2的值,我们的查找范围不会超过这里。比如8=3+5,我们查了3就结束了,不可能查到4以上。
  • 尺取,不断的修改左右端点,第一个满足题意的odd prime对就是差值最大的对。
#include<iostream>
#include<iomanip>
#include<string.h>
#include<vector>
#include<algorithm>
using namespace std;
#define MAX 1000005

bool prime[MAX];
vector<int> items;

int main() {
	//2是偶数,不是姬素数
	memset(prime, 1, sizeof(prime));
	prime[0] = prime[1] = prime[2] = 0;
	for (int i = 2; i < MAX; i++) {
		if (prime[i])items.push_back(i);
		if (i == 2 || prime[i])for (int j = 2 * i; j < MAX; j += i)prime[j] = 0;
 	}
	int n;
	while (cin >> n && n) {
		//找到一个和n/2最接近的数
		int pos = lower_bound(items.begin(), items.end(), n) - items.begin();
		int l = 0, r = pos - 1, sign = 0;
		while (r >= l) {//等于也是可以的
			int sum = items[l] + items[r];
			if (sum == n) {
				sign = 1; break;
			}
			if (sum > n)r--;
			else l++;
		}
		if (sign) printf("%d = %d + %d\n", n, items[l], items[r]);
		else cout << "Goldbach's conjecture is wrong." << endl;
	}
}
发布了186 篇原创文章 · 获赞 13 · 访问量 9326

猜你喜欢

转载自blog.csdn.net/csyifanZhang/article/details/105156867
今日推荐