什么是埃氏筛选?
埃拉托斯特尼筛法,简称埃氏筛 或 爱氏筛,是一种由希腊数学家埃拉托斯特尼所提出的一种简单检定素数的算法。 要得到自然数n以内的全部素数,必须把不大于根号n的所有素数的倍数剔除,剩下的就是素数。 要得到自然数n以内的全部素数,必须把不大于 的所有素数的倍数剔除,剩下的就是素数。 ——来自百度百科
简而言之:就是把素数的倍数的数 全部剔除掉 剩下的数就是素数
比如:0 1 2 3 4 5 6 7 8 9 10 11
0和1 不是素数 先剔除
为: 2 3 4 5 6 7 8 9 10 11
2 是素数 剔除2的倍数的数
为:2 3 5 7 9 11
在读取下一个数字 3 为素数 再剔除3的倍数的数
为:2 3 5 7 11
再继续循环
最后 2 3 5 7 11 即为所求范围内的 全部素数
代码如下:
时间复杂度O(nloglogn)
题目1:
求0到n范围内的所有素数
#include<iostream>
using namespace std;
#include<vector>
int prime[1000];
int main()
{
int n;
cin >> n;
for (int i = 0; i <= n; i++)
{
prime[i] = 1;
}
prime[0] = 0;
prime[1] = 0;
for (int i = 2; i < n + 1; i++)
{
if (prime[i] == 1)
{
for (int j = i * i; j < n + 1; j = j + i)
{
prime[j] = 0;
}
}
}
for (int i = 0; i <= n; i++)
{
if (prime[i] == 1)
cout << i << endl;
}
return 0;
}
题目2:
P1314 - 线性筛素数 - HAUEOJ (haueacm.top)http://www.haueacm.top/problem.php?id=1314
#include<iostream>
using namespace std;
#include<vector>
int main()
{
int n;
int m;
cin >> n>>m;
vector<int>prime(n+1,1);// 长度为n+1,因为下标为所要判断的数字
vector<int>isprime(n);
prime[0] = 0;
prime[1] = 0;
for (int i = 2; i < n+1; i++)
{
if (prime[i] == 1)
{
for (int j = i * i; j <n+1; j = j + i)
{
prime[j] = 0;
}
}
}
int p = 0;
int x = 0;
for (int i = 0; i < n+1; i++)
{
if (prime[i] == 1)
{
isprime[++p] = i;
}
}
while (m--)
{
cin >> x;
cout << isprime[x] << endl;
}
return 0;
}
欧拉筛:
埃氏筛 会重复筛 增加时间复杂度 为了更优化 将使用欧拉筛
欧拉筛:在埃氏筛的基础上(也是用素数的倍数去筛掉非素数 ,合数只能被它的最小质因数来筛,比如20 ,只能用它的最小质因数2来筛除,不能用4,或者5去筛除)
不同于埃氏筛的是 欧拉筛不会重复筛一个数 从而降低了时间的复杂度
题目:求0到n范围内的所有素数
欧拉筛的核心就是 if(i%isprime[j]==0)break;
1.代码中i消去合数的作用就是当做倍数
2.保证每个合数使用它的最小质因数来筛除
当i%prime[j]!=0时,prime[j]一定小于i的最小质因数,则prime[j]一定是prime[j]*i的最小质因数;
当i%prime[j]==0,prime[j]是i的最小质因子,prime[j]也是prime[j]的最小质因子,所以prime[j]是prime[j]*i的最小质因子;
当i%prime[j]==0 时,如果继续运算i*prime[j+1] 不break 则prime[j+1]*i 的质因数为prime[j+1] 但prime[j+1]不是最小质因数 (不符合用最小质因数来筛的条件)
比如:i=20,prime[j]=2; prime[j]=2 是i*prime[j]=40的最小质因数
如果继续运算 i=20, prime[j+1]=3 , 则 prime[j+1]=3 就不是 i*prime[j+1]==60 的最小质因数
因为 当i%prime[j]==0,prime[j]是i的最小质因子 且 prime[i]小于prime[j+1]
所以prime[i]是 i*prime[j+1]==60的最小质因数
#include<iostream>
using namespace std;
#include<vector>
int main()
{
int n;
int m;
cin >> n;
int count = 0;
vector<int>prime(n + 1, 1);
vector<int>isprime(n);
prime[0] = 0;
prime[1] = 0;
for (int i = 2; i <= n; i++)
{
if (prime[i] == 1) { isprime[count++] = i; }
{
for (int j = 0; j <= count; j++)
{
if (i * isprime[j] > n)
{
break;
}
prime[i * isprime[j]] = 0;
if (i % isprime[j] == 0)
{
break;
}
}
}
}
for (int i = 0; i <= n; i++)
{
if (prime[i] == 1)
cout << i << endl;
}
}