线性筛素数(小总结)

线性筛素数


线性筛素数是一种常用的判断素数的方法,与传统方法相比,时间复杂度更优,O(n),属于空间换时间的思想。其复杂度相比传统

复杂度对比
  时间 空间
传统方法 O(n sqrt n) O(1)
普通筛 O(n log log n) O(n)
线性筛 O(n) O(n)

 

 

 

 

 

非常适合大规模的询问(打板子),总体消耗不大。貌似又叫欧拉筛。普通筛也叫埃氏筛。

//貌似是这样撒


Talk is cheap, show me the code

int prime[100001];  //prime[1...100001]表示素数,prime[0]为计数器,统计素数个数
bool mark[maxn];    //mark[i]=true表示i不是素数

void getPrime(int n) {
    //0, 1 均不是素数
    mark[0] = mark[1] = true;

    for(int i=2; i<=n; i++)
     {
        //如果没标记就加入素数集
        if(!mark[i]) {
            prime[++prime[0]] = i;
        }
        //所有已知素数与i的积均 不为素数
        for(int j=1; j<=prime[0] && prime[j]<=n/i; j++) {//n/i防溢出
            mark[i*prime[j]] = true;      //标记不是素数
            if(i%prime[j]==0)   break;    //防重复,每个数都应被它的最小质因数筛掉
        }
    }
}

具体原理参见各位大佬的博客,大体上依靠的是素数的定义(除本身和1外没有其他因子),得出两数(>=2)的乘积必定为素数,这就是普通筛的原理,复杂度很接近O(n)。但是加上if(i%prime[j]==0) break;之后,就不会出现重复删除的情况,效率就提高了

Update 

每一个合数都应该被它的最小质因数筛掉,当满足if(i%prime[j]==0) 时, prime[j]为i*prime[j]的最小质因子(可以证明), prime[j]也是i*prime[j...]的质因子, 他们都已经被删掉了,所以不需要再删。这里是埃氏筛与欧拉筛的区别,当n=10^7时,时间快了1倍 。   

你可能感兴趣的:(数据结构&算法)