PAT Basic(乙级)---1007(20分)素数对猜想

让我们定义dn​​为:d​n​​=p​n+1​​−p​n​​,其中p​i​​是第i个素数。显然有d​1​​=1,且对于n>1有d​n​​是偶数。“素数对猜想”认为“存在无穷多对相邻且差为2的素数”。

现给定任意正整数N(<10​5​​),请计算不超过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);
  }

结果:

。。。。运行超时?! 


 

调试:

运行超时可能情况:

  1. 死循环
  2. 数据太大时,超过了运行时间上限

死循环是不可能死循环的,赋值的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

舒服。

 

 

 

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值