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

it2023-09-10  71

题目描述:

给定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; }
最新回复(0)