回文质数是洛谷中题号为P1217的一道题目。题目要求所设计的程序可以在短时间之内,从给定的范围之内(5到100000000)寻找到所有的回文质数。以下是我个人对该题目的一些思考。
想要找到回文质数有多种方法,一种是暴力枚举再通过相应的方法去判断,另一种是直接生成回文质数,还有一种是先生成质数再判断回文数。这些方法都有自己的优劣所在。不对其进行相应的处理都会导致最终的测试TLE。由于能力所限,并没有找到合适的生成回文数的方法,所以接下来对其余两种算法分别进行阐述:
// 以下是暴力枚举
cin >> a >> b;
if(a % 2 == 0)
a++;
for(int i = a; i <= b; i += 2){
// 以下所用函数分别为:是否是范围内,是否是回文数,是否是质数
if(isEven(i) && isPrimeRev(i) && isPrime(i)){
cout << i << endl;
}
if(i > 9989899) break;
}
// 以下是生成质数(埃氏塞法)
bool book[100000001];
memset(book, true, sizeof(book));
book[1]=false;//1不是质数
int n=sqrt(b);
for (int i=2;i<=n;i++) {
if (book[i]) {
//质数的倍数绝对不是质数,把所有质数的倍数全部设为false
for (int j=2;j<=b/i;j++)
book[i*j]=false; // i*j<=b
}
}
当然,想要得到质数还可以使用其他的算法,后续会在其他的文章之中阐述。用上面的两种算法可以较为快速的筛选出符合题意的质数。
下面阐述如何快速的找出回文数。
// 从下列代码中不难得出,从0开始逐渐更新temp变量,并将需要判断的数不断地消去第一位数,即为大概的思路。
int isPrimeRev(int n){
int temp = 0, m = n, flag = 0;
while(n != 0){
temp = temp * 10 + n % 10;
n /= 10;
}
if (temp == m) flag = 1;
return flag;
}
通过这两种方法,就可以实现快速得到相应的回文质数。
以下是我的解题代码:
#include<bits/stdc++.h>
using namespace std;
unsigned int a,b;
int isEven(int n){
if((1000< n && n < 9999) || (100000 < n && n < 999999))
return 0;
return 1;
}
int isPrimeRev(int n){
int temp = 0, m = n, flag = 0;
while(n != 0){
temp = temp * 10 + n % 10;
n /= 10;
}
if (temp == m) flag = 1;
return flag;
}
int isPrime(int n){
if(n == 2) return 1;
for(int i = 2; i <= sqrt(n); i++){
if(n % i == 0) return 0;
}
return 1;
}
int main(){
cin >> a >> b;
if(a % 2 == 0)
a++;
for(int i = a; i <= b; i += 2){
if(isEven(i) && isPrimeRev(i) && isPrime(i)){
cout << i << endl;
}
if(i > 9989899) break;
}
return 0;
}
最后,其他筛选质数的方法,仍需整理一番。