个人整理, 转载请注明出处,thx.
最普通的线性筛法, earthson的代码比较优秀了
比赛的时候很少有同时卡筛法时间和空间的。
线性筛法的定义凭我自己理解就是对每个范围内的数每个合数标记一次且仅一次,没标记的就是素数,这样遍历每个数的次数就是一个常数,因此总时间是线性的。
常用的线性筛法大多考虑的是每个合数都会拆成一个它最小的质因子乘以某个数,所以有2种方法:
1.通过枚举每个已判别的素数p来筛掉以它为最小质因子的合数,通常从p*p到N。
2.通过枚举每个数将它与已筛出的素数顺序相乘直到该数能整除某个素数为止(这样保证了所乘素数是最小的质因子)。
这个范围可以是1到N,也可以是(2, N]间的奇数(当然记录素数时要加上2),也可以是(3,N] 间的(不能整除3的奇数(earthson给出了一个))
还有一个小技巧是位模式标记, 因为c/c++中bool 型都是一个字节的,如果换成1个int存32个标记位,再利用位运算,空间上会省很多大约是原来的1/8,时间上也不会多耗费多少。
另外还有一个省空间的小技巧是将筛表循环使用,重复覆盖原来的筛表(这个不再这里赘述)。
只筛奇数的情况, 生成一个isprime的bool数组,不能表示2,但是也可以理解没isprime[1]同时表示了2和3,不过这样做没什么意义。
/// N&#