题目:
蒜头君对既是素数又是回文的数特别感兴趣。比如说 151 既是素数又是个回文数。回文数是指从左到右读和从右到左读都一样的数。
现在小王想要你帮助他找出某个范围内的素数回文数,请你写个程序找出 a 跟 b 之间(包含 a 和 b)满足条件的数。
输入格式
输入 a 和 b (2 ≤ a < b ≤ 100,000,000)。
输出格式
按从小到大输出 a, b 之间所有满足条件的素数回文数,一个数占一行。
输出时每行末尾的多余空格,不影响答案正确性
样例输入
2 200
样例输出
2 3 5 7 11 101 131 151 181 191
提醒:本文只对素数做出解释,回文代码大家可以自己模拟代码结果。
#include <iostream>
using namespace std;
int a, b;
int main() {
cin >> a >> b;
for (int i = a; i <= b; i ++) {
int x, y;
y = 0, x = i;
while (x > y) {
y = y * 10 + x % 10;
x /= 10;
}
if (x == y || x == y / 10) { // while 到此处是回文数的判断
int find = 0;
for (int j = 2; j * j <= i; j ++) {
if (i % j == 0) {
find = 1; // for 中素数判断是对暴力求解的一种改进(文末有解释)
}
}
if (find == 0)
{
cout << i << endl;
}
}
}
return 0;
}
对素数的判断中 for(int j = 2; j * j <= i; j ++) 进行一个通俗的解释:
就是一个非负数 n ,它如果不被 1 和自身分解,想要被其它的整数分解,那么分解的结果就是这两个数一定是在 sqrt(n)的两侧,一个数在 sqrt(n)的左侧,一个数在 sqrt(n)的右侧。
例如:n = 100 sqrt(n)= 10;
那么:2 * 50 = 100
5 * 20 = 100
在一个算式中,2 和 5 都在 10 的左侧, 50 和 20 都在 10 的右侧。
以前我的做法是遍历到 n/2,其实这样也是有一定误差的(大家可以想一想有什么误差),我们不需要遍历到 n , 也不需要遍历到 n - 1 ,我们只需要遍历到 sqrt(n)即可。
推荐大家写成 for ( int i = 2; i * i <= n; i ++) ,
若要写成 for ( int i = 2; i <= sqrt(n); i ++) , 还需要添加头文件#include <cmath> 。
提醒:本文的代码在 Dev C++ 中能正确运行;在计蒜客中提交有超时的概率。回文和素数都有优化的空间,大家可以进一步优化。