镜面质数 题解

题目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}\)

posted @ 2024-08-03 16:18  Firra3500  阅读(7)  评论(0编辑  收藏  举报