回文素数 prime palindrome(构造回文数)

本文介绍了一种高效算法,用于找出指定区间内的回文素数。通过构造回文数并检查其素性,而非逐一检查所有数值,显著降低了计算复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:

给定x,y,输出[x,y]中所有的回文素数(即既是回文数也是素数,比如101, 131),其中5 <= a < b <= 1000000000
时间限制:5s
内存限制:512M

思想:

1.暴力枚举所有的数据

考虑从5~1e9枚举,先判断是不是回文数,然后判断是不是素数,然后输出(当然也可以反过来,先判断是不是素数然后判断是不是回文数),这里时间上肯定会有差别,首先回文数与素数的密度是不一样的,以及,判断回文数与判断素数的时间复杂度也是不一样的,那么这里的时间复杂度至少是O(n)的(其实大很多),可以考虑一下时间限制,肯定是过不了的(至少要几十秒)。当然这也是最容易想到的办法。

2.给定素数

假设我们只需要判断其中一个呢,首先考虑给定素数,然后去判断回文数,于是乎我们想到了打素数表,然后去直接去表里面找到素数然后判断是不是回文数即可(那为什么不直接存所有的回文素数然后直接输出呢)。很显然这样是不行的,因为会被手动ban掉。

3.给定回文数

这与做法2有什么不一样呢?当然有,素数我们只能先存下来,然后直接使用,但是回文数我们不需要存,因为它可以被构造出来,比如101,那么可以由10得到(即10*10+1),再比如12321可以由123得到,当然同样可以枚举位数为偶数的回文数如1221,但是这里有一个数学定理,即所有偶数位的回文数都是11的倍数(除了11,除非你认为它是一倍),其实不知道这个定理也无妨,假设偶数位数的回文数和奇数位一样多,那么我们顶多就增加一倍的时间,可是我们已经解决了最大的问题就是去遍历1e9,为什么这么说呢,因为你会发现,要构造1e9的回文数,只需要1e5的数据量,即1 000 000 00 1可以由100000得到,所以说我们只需要从5遍历到100000即可,这也就是为什么我们说增加一倍的时间不重要的原因了,因为相比于1e9,多跑一遍1e5要快得多,那么我们就确定了解决的方式,即构造回文数,然后判断是否是素数即可。(不会真有人不会构造回文数吧?),不必考虑从什么时候开始,不妨每次都从5开始,其实影响并不大,只要回文素数大于x再输出即可。当然不必每次都枚举到1e5,适当时候break即可。当然11是需要额外判断的。

构造回文:

1234 -> 12343 -> 123432 -> 1234321

4.代码

#include<stdio.h>

int is_prime(int x) {
	if(x == 2) return 1;
	for(int i = 2; i*i <= x; i++) {
		if(x % i == 0) return 0;
	}
	return 1;
}

int main() {
	int a, b;
	scanf("%d%d", &a, &b);
	for(int i = 5; i <= 100000; i ++) {
		if(i == 9 && a <= 11 && b >= 11) puts("11");
		int tmp = i/10, ans = i;
		while(tmp > 0) {
			ans *= 10;
			ans = ans + tmp%10;
			tmp /= 10;
		}
		if(ans > b) break;
		if(ans >= a && is_prime(ans)) printf("%d\n", ans);
	}
	return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值