一,简介:欧拉筛法是一种线性筛,是筛选素数的高效方法(不重复筛选),合数都被最小素因子筛去。
二,图码详解
integer | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|---|
tag | false | false | false | false | true | false | true | false | true | true |
primes | 2 | 3 | 5 | 7 | ||||||
integer | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
tag | true | false | true | false | true | true | true | false | true | false |
primes | ||||||||||
intager | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
tag | true | true | true | false | true | true | true | true | true | false |
primes |
for (int i = 2; i <= n; i++)循环遍历前n个数当i指向2,判断是否是合数(if (!hs[i]))
如果不是,即2存入primes[0]中。
用for (int j = 0; primes[j] * i <= n; j++)遍历素数//primes[i]<=n限制出界(出界不用标记)
用hs[primes[j] * i] =true// 即hs[2*2]=true标记合数
(素数乘一个非零数得到的为合数 例如2*3=6,6为合数)
i指向3,存入primes[1]中 用ha[prinmes[j]*i]标记2*3,3*3
i指向4,if (!hs[i])判断为合数不存。用for (int j = 0; primes[j] * i <= n; j++)遍历素数,
用hs[primes[j] * i] =true标记合数//2*4,注意:不标记3*4,if (i % primes[j] == 0)break;//若primes[i]是合数i的最小素因子结束本轮遍历。防止重复标记12用最小质因子2标记即2*6。
i指向5,存入primes[2]中。 用ha[prinmes[j]*i]标记2*5,3*5,5*5
i指向6if (!hs[i])判断为合数不存。遍历素数,标记合数2*6
i指向7存入primes[3]用ha[prinmes[j]*i]标记2*7,3*7|
primes[j] * i <= n(故5*7,7*7不遍历)
后面以此类推。。。。
三,代码展示
#include<iostream>
#include<ctime>
using namespace std;
int primes[1000000];//用来储存素数
int tag[1000000];//用来做标记储存合数
int k = 0;
int main()
{
int n; cin>>n;
double s = clock();//检测时间起始位置
for (int i = 2; i <= n; i++) {
if (!tag[i])primes[k++] = i;//如果h[i]即i为非合数存入素数i
for (int j = 0; primes[j] * i <= n; j++)//primes[i]<=n限制出界(出界不用标记)
{
tag[primes[j] * i] =true;//合数primes[i]*i
if (i % primes[j] == 0)break;//若primes[i]是合数i的最小素因子结束本轮遍历。防止重复标记。
}
}
double e = clock();//检测时间结束位置。
printf("%.01fms", e-s);//输出时间段。
for (int i = 0; i < k; i++)cout << primes[i] << " ";
return 0;
}
double s=clock();
double e=clock();printf("%.01fms",e-s)//可以用这个函数比较和其他方法的筛选时间。(clock在头文件ctime中)。