思路很简单,主要卡在了运行时间上。本题主要考察数学知识
因为先判断的回文数,搜索素数的次数大大减小,因此函数比筛法要快。如果大量搜索素数,筛法会比函数快很多
需要知道的:
1.偶数位数回文数(除11)必定不是质数(自行百度),所以只要运行到10000000。
2.偶数肯定不是质数。这样至少排除一半多的数据量。
易错样例
输入样例: 5
输出样例: 100000000
最初的代码(普通筛选素数):
#include
using namespace std;
int prime(int n)//判断质数
{
for (int i = 3; i <= sqrt(n); i += 2)//偶数不是质数
if (n%i == 0)return 0;
return 1;
}
bool huiwen(int n)//判断回文数
{
int i = n, m = 0;
while (i > 0)
{
m = m * 10 + i % 10;
i /= 10;
}
return m == n;
}
int main()
{
int a, b;
cin >> a >> b;
if (b >10000000)b = 10000000;//偶数位数回文数(除11)必定不是质数(自行百度),所以可以只运行到10000000
for (int i = a % 2 == 0 ? a + 1 : a; i <= b; i += 2)
{
if (i > 10000000)break;
if (huiwen(i)&&prime(i))
cout << i << endl;
}
return 0;
}
埃拉托斯特尼筛法:
在筛质数时,我们会发现,筛去2后,2的倍数4、6、8等一定不是素数;筛去3后,3的倍数6、9、12等一定不是倍数。简单模拟这个过程。时间复杂度是O(n*lglgn)。
#include
using namespace std;
const int SIZE = 10000005;
int prime[SIZE];//数组设为全局变量不容易爆栈
bool isHw(int n)//判断回文数
{
int i = n, m = 0;
while (i > 0)
{
m = m * 10 + i % 10;
i /= 10;
}
return m == n;
}
int main()
{
int a, b, i, j;
cin >> a >> b;
if (b >10000000)b = 10000000;
for (int i = 0; i<SIZE; i++) prime[i] = 1; //先把每个数都定义为素数
for (int i = 2; i<SIZE; i++)//埃拉托斯特尼筛法
{
if (!prime[i]) continue;
for (int j = i * 2; j<SIZE; j += i) prime[j] = 0; //将i的倍数标记为合数
}
for (i = a % 2 == 0 ? a + 1 : a; i <= b; i += 2)
{
if (i > 10000000)break;
if (isHw(i)&& prime[i])
cout << i << endl;
}
return 0;
}
线性筛法(欧拉筛法):
原理:对于任意合数,必定可以有最小质因子乘以最大因子的分解方式。因此,对于每个合数,只要用最大因子筛一遍,枚举时只要枚举最小质因子即可。