题目链接:点击查看
题目大意:给出一个a和b,求出区间[a,b]中所有回文质数,回文质数指的是一个数既是回文数也是质数
题目分析:首先质数好判断,我们只需要用欧拉筛预处理打好表即可,判断回文数我们也只需要用一个函数O(lgn)的时间就可以判断,但a和b的范围高达1e8,1e8*lgn最大能到1e9,评测机肯定是顶不住的,这个时候我们该怎么办呢,这里我们需要补充一下关于回文质数的几个小性质吧:
- 偶数位的回文串必不可能是素数
- 偶数一定不是素数(废话)
我也不太会证明,但有了上面的第一个结论后,我们就可以直接将1e8的时间复杂度下降到了1e7,这样就能顺利AC了
代码:
#include<iostream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cctype>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<sstream>
using namespace std;
typedef long long LL;
const int inf=0x3f3f3f3f;
const int N=1e7+100;
int pri[N];
bool vis[N];
int cnt;
void P()//欧拉线性筛
{
vis[1]=true;
for(int i=2;i<N;i++)
{
if(!vis[i])
pri[cnt++]=i;
for(int j=0;j<cnt&&pri[j]*i<N;j++)
{
vis[pri[j]*i]=true;
if(i%pri[j]==0)
break;
}
}
}
bool check(int x)//O(lgn)判断回文数
{
int ans1=x;
int ans2=0;
while(x)
{
ans2=ans2*10+x%10;
x/=10;
}
return ans1==ans2;
}
int main()
{
// freopen("input.txt","r",stdin);
// ios::sync_with_stdio(false);
P();
int a,b;
scanf("%d%d",&a,&b);
for(int i=a;i<=b;i++)
{
if(i>=N)//剪枝,剪掉所有大于1e7的数
break;
if(!vis[i]&&check(i))
printf("%d\n",i);
}
return 0;
}