洛谷刷题_P217 [USACO1.5]回文质数 Prime Palindromes

题目

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同理。

看了一下别人的做法,好像用线性筛更快(欧拉筛),或者是打表的方法。有兴趣的师傅也可以尝试一下。

posted @ 2022-11-12 17:29  Jinx8823  阅读(63)  评论(0)    收藏  举报