题目
P217 [USACO1.5]回文质数 Prime Palindromes
题目链接
https://www.luogu.com.cn/problem/P1217
知识点
埃氏筛
原理:
要得到自然数n以内的全部素数,必须把不大于根号n的所有素数的倍数筛掉,剩下的就是素数。
首先给出要筛选的范围n,要找到n以内的素数。首先把2留下,然后找出2的倍数都筛掉;再用下一个质数3,然后把3的倍数都筛掉,接着再把5的倍数筛掉,以此类推。
如何判断一个回文数:
通过末位乘10,然后再加倒数第二位之后,再乘10,以此类推,最终用结果来判断是否和原数相等,相等则是回文数。
11的整除性质:
如果一个整数的奇位数字之和与偶位数字之和的差能被11整除,则这个数能被11整除。
code
#include <stdio.h>
#include<cstring>
#include<math.h>
bool prime[10000000];
int a,b;
bool is_pd(int x)
{
int y=x,num=0;
while(y!=0)
{
num=num*10+y%10;
y/=10;
}
if(num==x) return true;
else return false;
}
void isprime(int n)
{
for(int i=2;i<=n;i++)
{
if(prime[i])
{
for(int j=i*2;j<=n;j+=i)
{
prime[j]=false;
}
}
}
}
int main ()
{
memset(prime,true,sizeof(prime));
prime[0]=false;
prime[1]=false;
scanf("%d%d",&a,&b);
//这里通过11的整除性质来确定偶数位的回文数一定不是素数
//因为偶数位的回文数奇数位之和与偶数位之和的差是0,所以一定能被11整除
//由于大于等于10000000的数一定是偶数位所以不用考虑
if(b>=10000000) b=9999999;
isprime(b);
//if(a%2==0) a++;这里可以这么写,因为能被2整除的数一定不是素数
//for(int i=a;i<=b;i+=2),所以这里能够减少一定的循环次数
for(int i=a;i<=b;i++)
{
if(prime[i] && is_pd(i))
{
printf("%d\n",i);
}
}
return 0;
}
小结
这道题刚开始提交的时候先是runtime error,发现是数组开太小了。
然后数组开大之和,发现又有两个测试点过不了。由于没有办法下载数据。所以稍微看了一下别人的AC代码,发现是埃氏筛那里写的有点问题
本来我是这样写的
void isprime(int n)
{
for(int i=2;i<=sqrt(n);i++)
{
if(prime[i])
{
for(int j=i*2;j<n;j+=i)
{
prime[j]=false;
}
}
}
}
发现i和j的限制条件有点问题,应该改成是i<=n和j<=n,昨天的题目这么写是没有关系,但今天这么写发现是不太行的,问题应该是如果i只是小于sqrt(n)的话,在下面的循环筛素数的时候,有些数会筛不到,所以直接改成i<=n比较保险。j同理。
看了一下别人的做法,好像用线性筛更快(欧拉筛),或者是打表的方法。有兴趣的师傅也可以尝试一下。
标签:Prime,10,Palindromes,int,质数,素数,num,回文 From: https://www.cnblogs.com/Jinx8823/p/16884247.html