Java题解—1007 素数对猜想

原题

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

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

输入格式:
输入在一行给出正整数N。

20
结尾无空行

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

4
结尾无空行

解读

根据素数的定义,可以得素数都不为偶数(2除外)。
暴力破解可以很粗暴的把素数算出来,然后判断后一个素数减前一个素数的差是否为2 。
但是如我第一个版本,每个素数的判断都要重头开始对前面的奇数循环判断。整体代码复杂度O(n^2)。然后华丽超时了。(输入100000,循环了227564780次)

解决思路:怎么让判断素数的循环次数最小?
[百度判断素数的5种方法](https://jingyan.baidu.com/article/59a015e3f747d8b7948865e4.html)

其中关于对循环范围平方根的解释:

仔细思考就会发现,其实数字x的因数分成两大部分,一部分是小于x的平方根,另外一部分大于x的平方根,小于平方根和大于平方根的部分是一一对应的,
因而可以只判断从2到平方根的数字是否都能被整除即可。

代码

第一个超时版本:

package pat;
import java.util.Scanner;

/**
 * @Description
 */
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int num=scanner.nextInt();
        long start = System.currentTimeMillis();
        int sum=0;
        boolean flag=false;
        int count=0;
        int prev=3;
        
        for (int j=1;j<num+1;j+=2) {//按奇数增加

            for (int i = 3; i < j; i+=2) {
                sum++;
                if (j%i == 0) {//除得尽,不是素数退出
                    flag=false;
                    break;
                }
                flag=true;
            }

            if (flag) {

                if(j-prev==2){
                    count++;
                }
                prev=j;//前一个素数
//                System.out.print(j + " ");
            }
        }
        System.out.println("count:"+count);
        long end = System.currentTimeMillis();
        System.out.println(end-start+"毫秒");
        System.out.println("循环次数"+sum);
    }
}

第二个改进版,完成度100%:

参照了这里的博客
(捂脸)我就是标注了一下易错点。

package pat;



import java.util.Scanner;


public class Main {
    //判断是否为素数
    public static boolean isPrime(int num){
        if (num==3){
            return false;
        }
        if(num%2==0&&num!=2) return false;//排除不等于2的偶数 
        for (int i=3;i<=Math.sqrt(num);i+=2){//注意:这里要小于等于,防止平方根可以取整的时候进不来循环,导致误判返回true
            if (num%i==0){
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int range = scanner.nextInt();

        int count=0;
        for (int i=1;i<=range-2;i+=2){
            if (isPrime(i)&&isPrime(i+2)){//注意:这里会往后多算一个,所以范围要减2
                count++;
//                System.out.print(i+" ");
            }
        }

        System.out.println(count);
    }
}

posted @ 2021-10-10 17:43  Infinite_V胜  阅读(59)  评论(0)    收藏  举报