题目描述:
让我们定义dn为:dn=pn+1−pn,其中pi是第i个素数。显然有d1=1,且对于n>1有dn是偶数。“素数对猜想”认为“存在无穷多对相邻且差为2的素数”。
现给定任意正整数N
(<105),请计算不超过N
的满足猜想的素数对的个数。
输入格式:
输入在一行给出正整数N
。
输出格式:
在一行中输出不超过N
的满足猜想的素数对的个数。
输入样例:
20
输出样例:
4
分析:由题目中可以看出,这一对必是素数,且相差为2,所以很自然就想到了,可以先在N的范围求出所有的素数存起来,然后去遍历看哪两个相邻的素数相差为2,让计数自增一,最后输出即可。
所以问题的关键就变成了计算给定n范围内的素数问题了。
一般会想到直接遍历就好了,当然可以实现,但是时间复杂度太高,效率过低。
这里提供一种思路:当你发现2是素数的时候,那么2的倍数,像4,6,8,10等是不是都不可能是素数了?3是素数的时候,那么3的倍数也都不会是素数了,以此类推。你只需要从2开始(因为1不是素数),每遇到一个素数,然后将是其倍数的数全都删去,那么最后数组中就会只剩下是素数的数字了。
此题的代码如下:
#include<iostream>
using namespace std;
const int maxn=100005; //所能输入的n的最大范围;
bool is_prime[maxn]; // 判断是否为素数的数组;
int c=0; //记录prime数组的大小;
int prime[maxn]; //存储所有的素数;
void set_prime(int n)
{
for(int i=1;i<=n;i++)
is_prime[i]=true;
is_prime[1] = false;//1不属于素数;
for(int i=1;i<=n;i++){
if(is_prime[i]){
prime[c++]=i;
for(int j=i;j<=n;j+=i){ //去掉i的倍数数字;
is_prime[j]=false;
}
}
}
}
int main()
{
int n,count=0;
cin >> n;
set_prime(n);
for(int i=0;i<c;i++){
if(prime[i+1]-prime[i]==2&&i+1<n)
count++;
}
cout << count <<endl;
return 0;
}
小结:
以前我们遇到的总是简单的判断是不是素数就好了,这道题提升了一点高度,主要考虑的应该是算法复杂度的问题,因为如果不直接筛选素数,每一个数都去判断是不是素数,那么时间复杂度会过高。