闲聊:因为今早上有小姐姐交流这个题目,刚刚才知道这个原来是顺序结构的题,啊哈,我是用欧拉筛做的,当时还做了好久(埃氏筛会超时的),顺序结构的题目观看->深入浅出。
顺便复习一下欧拉筛->
输入:
5 500
输出:
5
7
11
101
131
151
181
191
313
353
373
383
题目分析:
1.顺序结构我就不讲了吧。
2.注意欧拉筛法,用vis数组标记合数的点(防止重复搜索),剩余的点与埃氏筛相似,都是标记质数的倍数->
复习一下埃氏筛的思想:从2开始,标记质数的倍数,加快筛选速度。(Onloglogn)
欧拉筛核心代码:
void ola(int m) {
memset(prime, 0, sizeof(prime));//常规填充
memset(vis, 0, sizeof(vis));
for (int i = 2; i <= m; i++) {
if (vis[i] == 0) {//未被标记,即是素数才可以进入
prime[cnt++] = i;用数组来升序记录素数的值的数组(只有素数的一个数组)
}
for (int j = 0; j < cnt && i * prime[j] <= m; j++) {
vis[i * prime[j]] = 1;//标记,不是素数的点
if (i % prime[j] == 0) {//重复的数不再筛选
break;
}
}
}
}
思考:为什么i%prime[j]==0之后就可以直接break呢?
表示i不是最小质因数,为了确保合数只被最小质因数筛掉,所以break掉,从而降低复杂度。
欧拉筛的时间复杂度只有(On)。
3.回文数判断不用说了吧(有点简单)。
4.还需要注意的一点是回文质数只能是奇数位:看看大佬们的解释->
//b<=10000000这个判断条件来自:除了11以外,一个数的位数是偶数的话,不可能为回文数素数。
// 如果一个回文素数的位数是偶数,则它的奇数位上的数字和与偶数位上的数字和必然相等;
// 根据数的整除性理论,容易判断这样的数肯定能被11整除,所以它就不可能是素数。
代码如下:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include<cmath>
#include<cstring>
#define maxn 10000008
using namespace std;
bool P[maxn];
int prime[maxn];
int vis[maxn];//标记数组
bool huiwen(int x) {
int y = x;
int num = 0;
while (y != 0) {
num = num * 10 + y % 10;
y = y / 10;
}
if (num == x) {
return true;
}
return false;
}
void ola(int m) {
int cnt=0;//计数器
if (m > 10000000) {
m = 10000000;
}
memset(prime, 0, sizeof(prime));
memset(vis, 0, sizeof(vis));
for (int i = 2; i <= m; i++) {
if (vis[i] == 0) {//未被标记,即是素数才可以进入
prime[cnt++] = i; P[i] = 1;
}
for (int j = 0; j < cnt && i * prime[j] <= m; j++) {
vis[i * prime[j]] = 1;//标记,不是素数的点
if (i % prime[j] == 0) {//重复的数不再筛选
break;
}
}
}
}
int main()
{
int n, m;
cin >> n >> m;
ola(m);
for (int i = n; i <= m; i++) {
if (i>10000000) {//八位数的时候就可以直接break掉,加快速度
break;
}
if (P[i]&&huiwen(i)) {
cout << i << endl;
}
}
}
撒花!所有的知识点还是要及时复习与巩固,也要不断的思考算法的过程。