题目地址:
https://www.luogu.com.cn/problem/P1217
题目描述:
因为
151
151
151既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以
151
151
151是回文质数。写一个程序来找出范围
[
a
,
b
]
(
5
≤
a
<
b
≤
100
,
000
,
000
)
[a,b] (5 \le a < b \le 100,000,000)
[a,b](5≤a<b≤100,000,000)(一亿)间的所有回文质数。
输入格式:
第
1
1
1行:二个整数
a
a
a和
b
b
b。
输出格式:
输出一个回文质数的列表,一行一个。
可以逐个遍历 [ a , b ] [a,b] [a,b]的每个数然后判断。这里有几个优化,首先偶数可以全部略过;其次,位数为偶数的回文数可以略过(除了 11 11 11),可以验证它们都是 11 11 11的倍数(可以将 x x x的十进制分解然后考虑其对 11 11 11取模,得出一个数能被 11 11 11整除的特征)。接着就对每个剩下的数做素数测试即可。代码如下:
#include <iostream>
#include <cmath>
using namespace std;
int a, b;
bool check(int x) {
int a = x, b = 0, cnt = 0;
while (x) {
b = b * 10 + x % 10;
x /= 10;
cnt++;
}
return a == b && (cnt % 2 || a == 11);
}
bool is_prime(int x) {
int j = sqrt(x);
for (int i = 2; i <= j; i++)
if (x % i == 0) return false;
return true;
}
int main() {
scanf("%d%d", &a, &b);
if (a % 2 == 0) a++;
for (int i = a; i <= b; i += 2) {
// 略过位数为大于等于4的偶数的数
if (i == 1001 || i == 100001 || i == 10000001) {
i = (i - 1) * 10 + 1;
continue;
}
if (!check(i)) continue;
if (is_prime(i)) printf("%d\n", i);
}
return 0;
}
时间复杂度 O ( ( b − a ) b ) O((b-a)\sqrt b) O((b−a)b),空间 O ( 1 ) O(1) O(1)。