镜面质数 题解
题目id:20313
题目描述
如果一个质数镜像反转(即将该数各个位上数字反转)后仍然是质数,那么就称这个质数为镜像质数。例如质数\(13\)反转后为\(31\),则\(13\)为一个镜像质数。
现在给定一个整数\(N\),请求出整数\(1\sim N\)范围内有几个镜像质数。
注意:求范围内的镜像质数时,质数和镜像反转后的数都需在范围内。
解题思路
由于该题数据范围较大,我在那儿对着数据乱开数组玄学\(\textcolor[RGB]{82,196,26}{
Accepted
}\)了。
咳咳,言归正传,\(1\leq N\leq 5×10^7\),就这么大的范围,你\(O(N\sqrt{N})\)能过才怪,怎么这么多人用朴素筛(教练原话,也包括本蒟蒻,只有\(50pts\ QwQ\))。
所以,我们这题思路非常明了:欧拉筛!
用欧拉筛筛出小于\(N\)的所有质数,再从\(1\)枚举到\(N\),如果这是个质数(欧拉筛有标记是否质数的数组)就将其反转(各神犇应该都会写吧),在判断反转后数是否小于\(N\)及是否质数,若是,答案加\(1\);若否,无事发生。
AC Code
#include<bits/stdc++.h>
#define N 4000007
#define INF 1e18
#define MOD 1000000007
#define LL long long
#define pb push_back
#define lb long double
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define IOS ios::sync_with_stdio(0),cin.tie(nullptr),cout.tie(nullptr)
using namespace std;
LL n,ans,p[N],cnt;
bool ip[50000007];
int main()
{
IOS;
cin>>n;
for(int i=2;i<=n;++i)
{
if(!ip[i])
p[++cnt]=i;
for(int j=1;j<=cnt&&p[j]*i<=n;++j)
{
ip[p[j]*i]=1;
if(i%p[j]==0)
break;
}
}
for(LL i=2;i<=n;++i)
{
LL t=i,sum=0;
if(!ip[i])
{
while(t)
{
sum=sum*10+t%10;
t/=10;
}
if(sum<=n&&!ip[sum])
++ans;
}
}
cout<<ans;
return 0;
}
Tip
if(sum<=n&&!ip[sum])
这句中sum<=n
必须放在!ip[sum]
,否则你会因为数组越界而玄学\(\textcolor[RGB]{52,152,219}{Time\ Limit\ Exceeded}\),要是你数组开太大,又会喜提\(\textcolor[RGB]{157,61,207}{Memory\ Limit\ Exceeded}\)。