让我们定义dn为:dn=pn+1−pn,其中pi是第i个素数。显然有d1=1,且对于n>1有dn是偶数。“素数对猜想”认为“存在无穷多对相邻且差为2的素数”。
现给定任意正整数N(<105),请计算不超过N的满足猜想的素数对的个数。
输入格式:
输入在一行给出正整数N。
输出格式:
在一行中输出不超过N的满足猜想的素数对的个数。
输入样例:
20
输出样例:
4
算法一思路:
- 题目的意思就是从2-n之间,有多少对相邻且差为2的素数对。那么首先要得到所有的素数,可以通过循环来判断。
- 建立数组list,设立两个索引,第一个索引为left,即第一个位置,初始化为0;第二个索引right为1。
- 当list[right]不为空时,循环判断是否为素数。.....我只能想到让list[right]这个数依次去对2到(list[right]-1)取余,如果值为0,那么就出循环,判断为非素数。
- 若为素数,继续判断是否相差为2。最后left=right,right加1。
- (但这样时间复杂度有点高呀,....首先要遍历链表所有值,每次还要循环取余判断该值是否为素数)
报错代码:
#include <stdio.h>
#include <stdlib.h>
int main(){
int n;
int i;
scanf("%d", &n);
if(n<=1) return 0;
int *list = (int*)malloc(sizeof(int)*(n-1));
//初始化
for(i=0;i<n-1;i++){
//赋的值为2到n
list[i] = i+2;
}
int left=0;
int right=1;
int count = 0;
while(list[right]!=NULL){
int k=1; //表示是否为素数
for(i=2;i<list[right];i++){
if(list[right]%i == 0){
k=0; //不是素数
break;
}
}
if(k==0){
right+=1;
}else { //若是素数进行判断
if((list[right]-list[left]) == 2){
count+=1;
}
left=right;
right+=1;
}
}
printf("%d",count);
}
结果:
。。。。运行超时?!
调试:
运行超时可能情况:
- 死循环
- 数据太大时,超过了运行时间上限
死循环是不可能死循环的,赋值的for循环不可能死循环,之后的判断素数的for也是不可能死循环的,i是正数,i++无论如何也是可以弹出循环的。while也是当list[right]!=-1时便跳出,边界添加n=1和2的时候都满足。
那就只能是数据太大时超过了题目规定时间上限,果然,时间复杂度太高了。
那。。。只能换一种方法了
算法二思路:
- 没有必要以数组来存储所有的数,因为判断素数对过后,前一个数之后就不会用到了,后一个数可以用一个临时变量暂时存储。比如3和5,判断完之后3就不用了,用临时变量存储5然后继续找。
- 判断k是否为素数只需要除到根号k就行了。一个数k如果不是素数那么一定存在若干个(不少于2个)因子,除去1之后,设最大的因子为p,p*p一定小于等于k,所以p<根号k。那么在2~根号k之间就可以找到最大因子,则不为素数。
代码:
#include<stdio.h>
#include<math.h>
int main()
{
int i,j,k,temp,n=0;
int s=2;
scanf("%d",&k);
if(k==1) return 0;
else{
for(i=3;i<=k;i++)
{
temp=sqrt(i);
//在2到根号i间找是否有因子
for(j=2;j<=temp;++j)
if(i%j==0) break;
//没有找到时j>=temp+1,则为素数
if(j>=temp+1)
{
if((i-s)==2)
n++;
s=i;
}
}
}
printf("%d",n);
return 0;
}
参考:http://https://blog.csdn.net/qq_41608020/article/details/79232447
舒服。