洛谷 P1217:[USACO1.5] 回文质数 Prime Palindromes
【题目来源】
https://www.luogu.com.cn/problem/P1217
【题目描述】
因为 151 既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 151 是回文质数。
写一个程序来找出范围 [a,b](5≤a<b≤100,000,000)(一亿)间的所有回文质数。
【输入格式】
第一行输入两个正整数 a 和 b。
【输出格式】
输出一个回文质数的列表,一行一个。
【输入样例】
5 500
【输出样例】
5
7
11
101
131
151
181
191
313
353
373
383
【算法分析】
● 如下判断素数的经典代码,当 n 较大时(如 1e7),会非常耗时,最终导致 TLE。
bool isPrime(int n) {if(n<2) return false;for(int i=2; i<=sqrt(n); i++) {if(n%i==0) return false;}return true;
}
本题问题规模达到 1e8,采用如上素数的经典代码必然会导致部分样例 TLE。好在回文质数问题的数据规模限制在 ≤7 位,故可据此进行优化,避免 TLE。
● 在算法竞赛或编程问题中,若需处理回文质数,一种方法是直接将数的范围限制在 ≤7 位,避免无效计算。因为不存在大于 10⁷ 的回文质数,最大回文质数为 9989899。另一种方法为欧拉筛法(又称线性筛法)结合回文判断求解。本题代码采用第一种方法。
● 欧拉筛法(又称线性筛法)
欧拉筛法(又称线性筛法)是一种高效筛选素数的算法,其核心特点是保证每个合数仅被其最小质因子筛除一次,从而实现 O(n) 的时间复杂度。欧拉筛法适用于大规模素数筛选(如 1e7 以上)的场景。欧拉筛法 C++ 代码如下所示。
#include <bits/stdc++.h>
using namespace std;const int maxn=1e6+5;
int prime[maxn];
bool st[maxn];int euler_sieve(int n) {int cnt=0;memset(prime,0,sizeof(prime));memset(st,0,sizeof(st));for(int i=2; i<=n; i++) {if(!st[i]) prime[cnt++]=i;for(int j=0; j<cnt && i*prime[j]<=n; j++) {st[i*prime[j]]=true;if(i%prime[j]==0) break;}}return cnt;
}int main() {int n;cin>>n;cout<<euler_sieve(n)<<endl;return 0;
}/*
in:8
out:4
*/
此代码适用于:https://www.acwing.com/problem/content/870/
【算法代码】
#include <bits/stdc++.h>
using namespace std;bool isPrime(int n) {if(n<2) return false;for(int i=2; i<=sqrt(n); i++) {if(n%i==0) return false;}return true;
}bool isHW(int x) {int t=0;int y=x;while(y) {t=t*10+y%10;y/=10;}return t==x;
}int main() {int le,ri;cin>>le>>ri;if(ri>=1e7) ri=9999999;for(int i=le; i<=ri; i++) {if(isHW(i) && isPrime(i)) {cout<<i<<endl;}}return 0;
}/*
in:
5 500out:
5
7
11
101
131
151
181
191
313
353
373
383
*/
【参考文献】
https://blog.csdn.net/hnjzsyjyj/article/details/148121301
https://blog.csdn.net/hnjzsyjyj/article/details/149547149
https://www.acwing.com/problem/content/870/
https://www.acwing.com/file_system/file/content/whole/index/content/3273/