PAT乙级1007,用C语言进行编程,实现素数对猜想

这一次呢,与之前所写的博客联动一下。

因为之前是对素数进行判断,那么这篇博客呢,就来完成PAT乙级中的1007这道题,也就是实现素数对猜想。

先来提一提该题目的要求:定义一个dn=pn+1 - pn, 其中呢pi是第i个素数,显然当素数pn+1为3时候,pn为2时,有满足dn=1,那么素数对猜想主要是为了满足dn=2的时候,满足该要求的素数对有多少对。

以20为例,显然存在3、5/5、7/11、13/17、19 这样四对素数对。

而我们要实现的,就是用代表来把这最后有多少对素数对的数量给输出出来。

审题分析,理清逻辑,流程图

要完成这道题目,其实难度不大,我们先理清逻辑:

1、先输入一个正整数。

2、要对输入的正整数从2开始先进行素数判断,这是我们之前那篇博客讲过的。

3、之后要进行条件语句判断,也就是判断pn+1-pn是否等于2,如果等于2,那就要进行计数。

流程图如下:

该流程图还是以串行结构为主。

代码实现

如该流程图所示,在知道了该题目的逻辑后,要实现该题目也非常简单了。

1、用scanf来输入整数N。

2、因为我们之前说过,要判断素数,其实非常简单,只需要把它与除了1与它自身以外的所有自然数相除,看能否整除,余数是否为零,如果为零,那就说明该数不是素数,反之,则说明该数为素数。

3、这道题可不是单纯的输入一个数进行判断,我们需要输入一个数,对它进行遍历,也就是用到一个for循环,而且要注意,是从2开始的,因为2是最小的素数,1并不是素数,之后,要再把该遍历的数与比它小且也是从2开始的素数相除,看能否整数来判断是否为素数。

这里判断是否为素数也同样是用count来计数然后对count数量大小进行判断得到的。

最后呢,再对pn+1-pn是否等于2来进行一定的判断,如果等于2,那也要开始计数,我这里用了一个cout来代替,好记忆一些。

#include<stdio.h>
int main(){
    int N = 0;
    int i = 0;
    int j = 0;
    int count = 0;
    int cout = 0;
    int pn = 2;
    int pm;
    scanf("%d", &N);
    for(i = 2; i <= N; i++){
        for(j = 2; j < i; j++){
            if(i%j == 0){
                count++;
                break;
            }
            else{
                count = 0;
            }
        }
        if(count == 0){
            pm = i;
            if(pm-pn==2){
                cout++;
            }
            pn = pm;
        }
    }
    printf("%d", cout);
}

测试结果:

最后的结果却让我大跌眼镜,该程序竟然超时了!!!

超时的原因在于时间复杂度太大,时间复杂度为O(n^2),或者说该程序计算了许多无效数据,导致最终的结果超时了,实在令人难以理解。

所以,我开始排查,并在网上找寻相关资料。

分析出一个原因:那就是我用来判断素数的方法比较差。

其实判断是否为素数,还有更简便的方法。

试想一下,给定一个值20,我们要判断它不是素数,是不是只需要除以2即可,同理,给定一个值21,它只要除以3就可以得到它不是素数,而至于4、6、8都可以这样得到。

仔细看,是否能发现,这些数的因子是不是都比它们的平方根要小。

也就是说,要判断这些数不是素数,只需要遍历到它们的平方根之前即可,也就是除到它们的平方根之前,那平方根之后的数据不就可以不计算了么。

想到这儿,我就赶紧去找C语言中平方根的方法了。

主要是用到sqrt函数,所以说,只需要把i定义成平方根即可,而且用到的库函数为#include<math.h>

代码实现 

#include<stdio.h>
#include<math.h>
int main(){
    int N = 0;
    int i = 0;
    int j = 0;
    int count = 0;
    int cout = 0;
    int pn = 2;
    int pm ;
    scanf("%d", &N);
    for(i = 2; i <= N; i++){
        int s = sqrt(i);
        for(j = 2; j <= s; j++){
            if(i%j == 0){
                count++;
                break;
            }
            else{
                count = 0;
            }
        }
        if(count == 0){
            pm = i;
            if(pm-pn==2){
                cout++;
            }
            pn = pm;
        }
    }
    printf("%d", cout);
    
}

测试结果:

 总结

总的来说,这道题难度不大,但是一定要注意,是否计算了无效数据,以及时间复杂度是否太大,m*n和n*n之间也是有着比较大的差距的。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值