算法-哥德巴赫猜想

问题概述


题目:算法-哥德巴赫猜想-

问题描述(原题是英文,这里是翻译过后的版本):
对于任意n大于或等于4的偶数,至少存在一对质数p1和p2,使n = p1 + p2。这个猜想至今没有被证实,也没有被否定。没人能确定这个猜想是否成立。然而,如果有的话,为一个给定的偶数,人们可以找到这样一对素数。这里的问题是,编写一个程序,对于给定的偶数,报告满足猜想条件的所有质数对的数目。
一个偶数序列作为输入。对应于每个数字,程序应该输出上述对的数量。注意,我们感兴趣的是本质上不同的对的数量,因此你不应该把(p1, p2)和(p2, p1)分别算作两对不同的对。

输入:
每个输入行都有一个整数。你可以假设每个整数都是偶数,大于或等于4小于2^15。输入的末尾用数字0表示。
输出:
每个输出行应该包含一个整数。输出中不应该出现其他字符。
样例输入:
4
10
16
0
样例输出:
1
2
2


1. 问题分析


1.1 算法核心

验证哥德巴赫猜想是经典的数学算法题,也就是数学问题用计算机来解决,因而算法核心就是数学模拟问题;


1.2 算法分析

因为我们要找素数对,所以得先有一个素数表嘛,第一步先写一个标准埃氏筛选法获得素数表,这里素数表可以取的大一点,因为系统输入的这个整数不超过215,所以我们的素数表可以取大一点。
有了素数表以后就可以数学模拟了,要找到一对素数满足素数对和等于某个整数,那肯定是一大一小,或者两个差不多大的素数,根据题目得知(p2,p1)和(p1,p2)这两对素数只算一组不同的素数对;
诶,这个时候我突然想到了算法中常用的小技巧-two pointers,定义两个指针,一个从素数表首开始,一个从素数表尾开始,这样不仅可以优化时间复杂度,也可以避免素数对的重复计数,于是就先根据输入的整数(以下简称为t)找到距离t最近的那个素数,然后让一个指针指向这个位置,然后另一个指针从素数表首开始,
就是把素数表想象成一个线性序列,
第一个指针指向首个元素,
第二个指针指向距离t最大的素数,
然后开始计算素数对的和,
若等于t,那么素数对计数器加一,之后第一个指针向右移动一位第二个指针向左移动一位,
若小于t说明不够大,那第一个指针向右移动一位,
若大于t说明不够小,那第二个指针向左移动一位,
这样不断匹配,直到第一个指针和第二个指针指向同一个元素,或者第一个指针指向的元素大于第二个指针指向的元素,此时终止循环,根据题目要求输出计数器的值即可;


2. 解决方案

#include <iostream>
using namespace std;

#define maxLength 40010

int n, primeTable[maxLength], primeCounts = 0, t;
bool primeSign[maxLength] = { 0 };
void findPrimeTable();
int GoldbachConjecture(int max);

int main()
{
	findPrimeTable();
	while (scanf("%d", &t) != EOF && t != 0)
	{
		t = GoldbachConjecture(t);
		printf("%d\n", t);
	}

	return 0;
}

void findPrimeTable()
{
	for (int i = 2; i < maxLength; i++)
	{
		if (primeSign[i] == false)
		{
			primeTable[primeCounts++] = i;
			for (int j = i + i; j < maxLength; j += i)
				primeSign[j] = true;
		}
	}
}

int GoldbachConjecture(int max)
{
	int counts = 0, tmp, overlapSign = 1;
	int *left, *right;

	left = primeTable;
	for(int i = 2; i < maxLength; i++)
	{
		if(primeTable[i] > max)
		{
			right = &primeTable[i - 1];
			break;
		}
	}
	while(*left <= *right && *right >= 2)
	{
		tmp = *left + *right;
		if(tmp == max)
		{
			counts++;
			left++, right--;
		}
		else if(tmp < max)
			left++;
		else
			right--;
	}

	return counts;
}

3. 资源分享

旗木白哉のGitHub:
https://github.com/YangMengHeng
C++ / C源代码下载地址:
https://github.com/YangMengHeng/myCode/tree/master/VSCode
Java源代码下载地址:
https://github.com/YangMengHeng/myCode/tree/master/Java
旗木白哉のblog源代码下载地址:
https://github.com/YangMengHeng/myCode/tree/master/%E6%97%97%E6%9C%A8%E7%99%BD%E5%93%89%E3%81%AEblog


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值