数论 欧拉线性素数筛

简述  

  素数筛是数论的门票(签到工具)

  很多数论问题都需要用到素数筛。

  本文将从作者自己的角度去阐述怎么写出欧拉线性筛。

素数筛的原理:

   必定有一个 不小于所有质因数   (  ≤  )  的质因数b 与 一个  大于等于所有因数   (  ≥  )  的因数c ( c ≠ 1) 乘积等于 合数a 

  本文 最小 是 不小于等于 的意思

   a = b * c ( a为合数,b 为 最小质因数 的质因数, c 为因数, 但 c 不等于 1 )

  至于为什么?

  因为

    假设 a ≠ 1,b 是质因数,c是因数,但 c 不等于 1

    a = b * c  

  那么,

    c = d * e,b,c,e中有一个 最小质因数 的 质因数。

  那么,

    假设是 e.是最小质因数

    a =  ( b * d ) * e ,

  因为

     d ≥ e 

     那么 ( b * d ) 构成了一个≥ c 的因数

  例如

    12 = 3*4 = 3 * 2 * 2= 2*6 , 那么最小质因数就是2,6 是 > 3,2,1 的因数。

    我们就需要 枚举这个 ≥ 每个因数 的数 去筛出合数,也就是确保每个合数被最小的质因数筛去

代码:

  实现细节: 

    要 求出 【2,n】的质数,

    1. 先从 小到大 枚举数 2~n 。

    (为什么要枚举到n ? 因为 n 可能为质数)

     ( 为什么从小到大枚举? 为了找出筛去合数的最小质因数)

     ( 为什么不会筛掉质数? 如果是枚举的数是质数,因为质数 = 1 * 最小质因数, 我们从 2开始枚举,肯定不会筛到质数,

     ( 为什么可以保证,n以内的合数肯定被筛去.? 每个合数被最小质因数筛去,也就是每个合数 大于等于所有因数的因数 已经被枚举过, 到了n,就自然只有 n * 最小质因数 = Y 这个值没有被筛了,虽然Y可能为质数...... )

    ( 我还有问题!为什么不会合数不会被重复筛!!! 因为我们可以确保每个合数只被他的最小质因数筛去。确保外层枚举的因数 >= 每个因数 

    2. 然后用 因数 乘上 对应的最小质因数  去找出 要筛掉的合数。

    3. 我们需要判断一下筛掉的 合数 的有没有超过 n 的范围。

    4. 同时需要保证,我们是用最小质因数筛掉这个合数的( 确保外层枚举的因数 >= 每个因数 ),这样就避免了重复筛。

    怎么保证?

         因为外层循环枚举因数,要确保每个合数是被最小质因数筛去,那么就得 确保外层枚举的因数 >= 每个因数 。

         a = b * c = d * e , c如果是最小质因数,那么 b ≥ d , e 。我们外层循环的 i 就得是 这个 b

         例如:如果 i % prime[j] == 0 ,那么 i == k * prime[j] ,  如果继续循环 j++ , 

         下个要筛的合数就是  i * prime[j+1] == k * prime[j+1] * prime[j] ( prime[j+1] > prime[j] )

         因为我们现在外层枚举的数是 i == k * prime[j] , 而当外层枚举的是 k * prime[j + 1]  才能去筛去。

         不用继续筛后面的数了,跳出循环,继续枚举因数。

那么 可以码出。

const int MAXN = 10000000;
int n,m;
int prime[MAXN];//保存质数
bool istPrime[MAXN];//不是质数
int cnt;

void sPrime(int n){
    istPrime[1] = true;
    for(int i = 2;i <= n; ++i){ //枚举大于与等于每个因数的因数
        if(!istPrime[i])
            prime[cnt++] = i; 
        for(int j=0;j<cnt && i*prime[j] <= n;j++){ //枚举最小质因数
            istPrime[i*prime[j]] = true;  //筛掉合数
            if(i%prime[j] == 0){ // 确保外层枚举的因数 >= 每个因数
                break; 
            }
        }
    }
}

推荐题目:

  https://www.luogu.org/problemnew/show/P3383

原文地址:https://www.cnblogs.com/--zz/p/10519322.html