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);
}
}