朴素的筛法在时间上的额外开销主要是因为同一个数会被筛掉好几次,所以线性筛法要做的就是利用数学方法保证每个和数只被筛掉一次。
原理:
每一个和数都可以分解成一个质数乘一个整数的形式,朴素筛法正是通过这样的策略去筛,但是这个条件很粗略,导致和数分解的方式不唯一。
在线性筛法中,和数(n)被分解成“n的最小质因数(p)* n的最大因数(a)”,(a可以=p);其中p为最小质因数时,a必然为最大因数,反过来也一样。
p与a的约束条件如下
1)a>=p;如果a>p那么a显然不是这个数的最大因数,所以a>=2
2)设最大因数(a)有最小质因数(m),则m>=p;
这确保了p是该和数(n)的最小质因数,p>m说明m是n更小的质因数,和p是最小质因数的假设矛盾;同时,也保证了a是n的最大因数
条件2)保证了和数能被分解成唯一形式,因此:对任意给定的一个整数a(a>=2),a与所有比其最小质因数(m)小的质数(p)相乘得到的n便是所有以a为最大因数的n。反之给出最小质数p也能按照这个条件得知a知否满足条件。
所以在线性筛法中要一边制作质数表,一边筛掉a与表内p的积。
代码出自演算法笔记,感谢这位台湾的朋友整理分享
const int N = 20000000; bool sieve[N]; void eratosthenes() { vector<int> prime; for (int i=2; i<N; i++) //i为最大因数 { if (!sieve[i]) prime.push_back(i); for (int j=0; i*prime[j]<N; j++) { sieve[i*prime[j]] = true; if (i % prime[j] == 0) break; } } }