PAT乙级(Basic Level)练习题 素数对猜想 (20)(筛选法)

题目描述
让我们定义 dn 为:dn = pn+1 - pn ,其中 pi 是第i个素数。显然有 d1 =1 且对于n>1有 dn 是偶数。“素数对猜想”认为“存在无穷多对相邻且差为2的素数”。

现给定任意正整数N (< 105 ),请计算不超过N的满足猜想的素数对的个数。

输入描述:
每个测试输入包含1个测试用例,给出正整数N。

输出描述:
每个测试用例的输出占一行,不超过N的满足猜想的素数对的个数。

输入例子:

20

输出例子:

4

解 题 思 路 : \color{blue}解题思路:
这道题其实也不难,关键的切入点是如何快速寻找素数。
最容易想到的就是穷举法,一一判断[1, n]中的每一个数i是否是素数,然后判断i + 2是否是素数。

不过经常刷题的一般都知道有一种快速求某段区间中的所有素数方法——筛选法。算法核心思想如下:
假设让你找出[1,1000]中的所有素数,你先初始化[2, 1000]中的数都是素数。然后开始遍历[2, 1000]区间

当n = 2时,是素数(这个是特殊起始值),
	把2的倍数468...1000 全被设为非素数,因为2是这些数的因子
当n = 3时,是素数(n < 3时没能筛除掉它,默认是素数,实际上它也是素数),
	把3的倍数6912...999全部设为非素数,因为3是这些数的因子
当n = 4时,早就被n = 2时筛除了。。。
当n = 5时,是素数(n < 5时没能筛除掉它,默认是素数,实际上它也是素数),
	把5的倍数101520...1000全部设为非素数,因为3是这些数的因子
....
当n = 1000时,找就n = 2筛除掉了。。。

最终没有被筛除掉235...的就是素数.

代 码 实 现 : \color{blue}代码实现:

#include 
#include 
using namespace std;

int main() {
    int n = 0, count = 0, tempNum;
    //primerTable[i]记录i是否是素数,记得初始化0、1不是素数
    bool primerTable[100001] = {false, false};
    while (scanf("%d", &n) != EOF) {
        count = 0;
        //初始化[2, 100000]所有都是素数
        memset(primerTable + 2, 1, 100001);
        //使用筛选法,找出[2, 100000]中的所有素数
        for (int i = 2; i < 100001 && i <= n; ++i) {
            if (primerTable[i]) {
            	//将i的倍数全设置为非素数(筛选法的核心)
                tempNum = i * 2;
                while (tempNum < 100001 && tempNum <= n) {
                    primerTable[tempNum] = false;
                    tempNum += i;
                }
                //现在i确定是素数了,如果i - 2也是素数,不就符合条件了么
                if (primerTable[i - 2]) {
                    count += 1;
                }
            }
        }
        printf("%d\n", count);
    }
    return 0;
}

PAT乙级(Basic Level)练习题 素数对猜想 (20)(筛选法)_第1张图片

你可能感兴趣的:(PAT)