java
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int a = scan.nextInt();
int b = scan.nextInt();
scan.close();
// 优化5:最大的回文质数是9989899
if (b > 9989899) {
b = 9989899;
}
// 优化1:如果a是偶数,从下一个奇数开始
if (a % 2 == 0) {
a++;
}
for (int i = a; i <= b; i += 2) { // 只检查奇数
// 优化2:排除偶数位数的数字(除了11)
if (i > 11 && String.valueOf(i).length() % 2 == 0) {
continue;
}
// 优化3:先判断回文
if (isPalindrome(i)) {
// 后判断质数
if (isPrime(i)) {
System.out.println(i);
}
}
}
}
// 优化4:高效的质数判断
public static boolean isPrime(int num) {
if (num < 2) return false;
if (num == 2) return true;
if (num % 2 == 0) return false; // 排除偶数
// 只检查到平方根,并且只检查奇数因子
for (int i = 3; i * i <= num; i += 2) {
if (num % i == 0) {
return false;
}
}
return true;
}
// 高效的整数回文判断,避免字符串转换
public static boolean isPalindrome(int num) {
if (num < 0) return false;
if (num < 10) return true;
int reversed = 0;
int original = num;
while (num > 0) {
reversed = reversed * 10 + num % 10;
num /= 10;
}
return original == reversed;
}
}
题目大意及思路
这道题目是要我们找出并输出为于你输入的两个数a和b之间的所有既是质数又是回文数的数,但是5<=a<=b<=1亿,这个题目本身难度不高,只是如果不筛选和优化判断方法则很容易出现超时现象。要想不超时,那么首先我们就得想办法把a到b的区间内的不可能是回文质数的数给筛选掉。那么该如何筛选呢首先我们知道所有的偶数必然不可能是质数,所以我们可以把偶数给筛选掉,还有我们所有位数长度是偶数的回文数必然可以被11整除,所以可以把所有的位数长度为偶数的数字筛选掉。
有人可能疑惑既然是所有位数长度为偶数的回文数不可能是质数那为什么要把所有的位数长度为偶数的数删掉,这是因为你可以把所有位数长度是偶数的数分为两类,一类是回文数一类是非回文数,而我们要找的是回文质数,既是回文数又是质数,第一类因为说过不可能是质数,而第二类甚至都不是回文数,所以所有的位数长度为偶数的数都要筛选掉。
java
// 优化5:最大的回文质数是9989899
if (b > 9989899) {
b = 9989899;
}
// 优化1:如果a是偶数,从下一个奇数开始
if (a % 2 == 0) {
a++;
}
先来看两个优化既然偶数不可能是质数那么区间下限a如果是偶数可以把它赋值为比它刚好大一的奇数,并且这个操作也方便了后面遍历时可以遍历到区间内的所有质数,还有,小于1亿的数里,最大的回文质数是9989899,所以大于9989899的数不用判断,当b大于9989899的时候直接赋值为9989899。
java
for (int i = a; i <= b; i += 2) { // 只检查奇数
// 优化2:排除偶数位数的数字(除了11)
if (i > 11 && String.valueOf(i).length() % 2 == 0) {
continue;
}
// 优化3:先判断回文
if (isPalindrome(i)) {
// 后判断质数
if (isPrime(i)) {
System.out.println(i);
}
}
}
}
这个首先注意这个循环,i += 2i是加2加2的递增的,前面又确保了区间下界是奇数所以确保了所有遍历到的数都是奇数。
同时
java
if (i > 11 && String.valueOf(i).length() % 2 == 0) {
continue;
}
又把所有的位数长度为偶数的数给筛选掉了。到此所有需要筛选的数已经全部筛掉。
接下来看判断部分的代码
java
// 优化4:高效的质数判断
public static boolean isPrime(int num) {
if (num < 2) return false;
if (num == 2) return true;
if (num % 2 == 0) return false; // 排除偶数
// 只检查到平方根,并且只检查奇数因子
for (int i = 3; i * i <= num; i += 2) {
if (num % i == 0) {
return false;
}
}
return true;
}
// 高效的整数回文判断,避免字符串转换
public static boolean isPalindrome(int num) {
if (num < 0) return false;
if (num < 10) return true;
int reversed = 0;
int original = num;
while (num > 0) {
reversed = reversed * 10 + num % 10;
num /= 10;
}
return original == reversed;
}
}
回文数反转的方法很容易看懂不多解释
这里只说说判断质数的方法,首先要记住一个数如果不是质数,那么这个数一定有一个不大于它开方后的因子。所以在判断质数的方法中只需要让这个数除到这个数的开方即可。