线性筛素数
代码实现:
基本思想
1.
如果 i 都是是素数的话,那简单,一个大的素数 i 乘以不大于 i 的素数,这样筛除的数跟之前的是不会重复的。筛出的数都是 N=p1*p2的形式, p1,p2之间不相等
2.
当前数字i是合数,则i=p1^a * p2^b * p3^c
(p1<p2<p3且均为素数),一次循环筛除小于等于p1的素数乘以i得到的数。比如p1之前有pi,pj和pk三个素数,则此次循环筛掉pi*i,pj*i,pk*i
和p1*i
,实现见代码的关键一,prime
里的素数都是升序排列的,break
时的遇到能整除的第一个prime[j]
就是这里的p1
。
结论:
1.一个数肯定不会被重复筛除
2.合数肯定被重复筛除。
关键:按照一个数的最小素因子筛选
图解:
参考:https://www.jianshu.com/p/f16d318efe9b
从图上我们看到,第一列筛掉的是最小素因子是2的数,第二列筛掉的是最小素因子为3的数,依次类推,可以把所有的合数都筛掉
因为是按照最小素因子筛选,所以可以保证每个数都只会被筛一遍
原理:
1. 任何一个合数都可以表示成一个质数和一个数的乘积
2. 假设A是一个合数,且A = x * y,这里x也是一个合数,那么有:
A = x * y; (假设y是质数,x合数)
x = a * b; (假设a是质数,且a < x——>>a<y)
-> A = a * b * y = a * Z (Z = b * y)
即一个合数(x)与一个质数(y)的乘积可以表示成一个更大的合数(Z)与一个更小的质数(a)的乘积!!!!
这也是理解代码中 if(i%primes[j] == 0)break;的关键
例如: 如果i = 8; 那么由于i%2 == 0; 因此对于i=8就只需要检查primes[1]=2即可,因为对于大于primes[1]的质数,像3,有:
8*3 = 2*4*3 = 12*2
也就是说24(8*3=24)并不需要在8时检查,在12时才检查