【Java】PAT (Basic Level) (中文) 1007 素数对猜想

本篇目录

前言

一、题目要求

二、思路分析

1.什么是素数对

2.判断素数

3.判断素数对

三、完整代码

总结


前言

本文的题目来自于PAT平台,PAT (Basic Level) (中文) 1007 素数对猜想 ,实现语言为Java。其中涉及了“判断一个整数是否为素数”的算法,我决定记录下来。


一、题目要求

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

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

输入格式:

输入在一行给出正整数N

输出格式:

在一行中输出不超过N的满足猜想的素数对的个数。

输入样例:

20

输出样例:

4

二、思路分析

1.什么是素数对

根据已知信息,如果正整数 m 与正整数 (m+2) 都是素数(质数),那么这就是一个素数对。对于题目给定的计算范围 N ,要求 m+2 <=N ,这才能将这个素数对计算在内。

2.判断素数

要计算素数对的数量,其中必然要调用一个功能为“判断所给整数是否为素数”的函数。那么不妨先把这个函数实现。为了尽可能优化代码,首先分析一下素数(质数)都有哪些特点。

① 1不是素数也不是合数,不大于5的素数只有2 3 5 三个,其中包含了素数对(3,5)。当N≤5时这是比较特殊的情况,应当单独进行判断。

② 在大于5的数中,所有素数的个位数字都是1 3 7 9 中的一个。这可以通过取余运算来判断。

③ 在大于5的数中,所有的素数都只可能是(6n-1)或者(6n+1),其中n是正整数。(这条结论来自百度。)首先要判断所给的整数是否有可能是素数,如果所给数字不是(6n-1)或者(6n+1)那就一定不是素数。而对于可能的素数,就要通过因数分解法进一步判断。

④ 每个合数都能分解为素数的乘积

只要判断每个可能是素数的整数,是否是给定整数n的因数,就可以了。这里要注意,不用把从1到n的每一个整数都作为因数都判断一遍,只要 要判断的整数的乘方≤n 就可以了。

下面是判断给定整数是否为素数的代码,时间复杂度为O(√n)。

    //判断一个整数是否是素数  时间复杂度为O(√n)
    private static boolean ifsushu(int t){
        //判断特殊值
        if(t==2 || t==3 || t==5)  return true;
        //若尾数不是1 3 7 9 则一定不是素数(10以上的数)
        if(t%2==0 || t%5==0)  return false;
        //若此数不是6n+1或者6n-1,则一定不是素数(10以上的数)
        if((t+1)%6!=0 && (t-1)%6!=0)  return false;
        //遍历检查(合数一定能分解为质数的乘积)
        for(int i=1;Math.pow(6*i-1,2)<=t;i++)
            if(t % (6*i-1) == 0 || t % (6*i+1) == 0)
                return false;
        return true;
    }

3.判断素数对

这一步就很容易了,只要在给定N的范围内,通过循环遍历每一个整数,用一个计数器t来记录素数对的数量,就可以了。不过,为了尽可能优化算法,对于N>5的情况,只对可能为素数的整数进行判断,其它的整数就不用算了。这一层循环的时间复杂度为O(n)。

要注意的是,在≤5的范围内还有一对(3,5)素数对,因此计数器的初始值要设置为1 而不是0 。


三、完整代码

算法整体的时间复杂度为O(n√n)。 

import java.io.*;
class Main{ //给定正整数n,计算不超过n的素数对的数量 时间复杂度O(n√n)
    public static void main(String[] args) throws IOException{
        //接收输入
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        //特殊值
        if(n < 5){  //若给定数字<5,直接打印0 然后返回
            sop(0);
            return;
        }
        //计算素数对的数量 
        int t = 1;  //计数器,素数对个数(初始值为1是预加上3 5 这一对)
        for(int i = 1;6*i+1<=n;i++)
            if(ifsushu(6*i-1) && ifsushu(6*i+1) )
                t++;
        sop(t);  //打印输出
    }
    //判断一个整数是否是素数  时间复杂度为O(√n)
    private static boolean ifsushu(int t){
        //判断特殊值
        if(t==2 || t==3 || t==5)  return true;
        //若尾数不是1 3 7 9 则一定不是素数(10以上的数)
        if(t%2==0 || t%5==0)  return false;
        //若此数不是6n+1或者6n-1,则一定不是素数(10以上的数)
        if((t+1)%6!=0 && (t-1)%6!=0)  return false;
        //遍历检查(合数一定能分解为质数的乘积)
        for(int i=1;Math.pow(6*i-1,2)<=t;i++)
            if(t % (6*i-1) == 0 || t % (6*i+1) == 0)
                return false;
        return true;
    }
    //打印函数
    private static void sop(int n){
        System.out.println(n);
    }
}

总结

通过这个练习,我进一步了解了素数以及素数的判断算法,有趣~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值