欧拉筛(线性筛)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了欧拉筛(线性筛)相关的知识,希望对你有一定的参考价值。

素数筛,就是按照顺序把合数踢掉,剩下的是素数。

欧拉筛是一种O(n)求素数的筛法。他避免了埃拉特斯特尼筛法对同一数的多次筛除。

欧拉筛的原理是只通过数的最小质因数筛数。

先上代码:

#include <cstdio>
using namespace std;

const int maxn=10000000;
int n, m, prime[maxn], isnt_prime[maxn], tot;

void get_prime(int n){
    isnt_prime[0]=isnt_prime[1]=1;
    for (int i=2; i<=n; ++i){
        if (!isnt_prime[i]) prime[++tot]=i;
        for (int j=1; j<=tot&&i*prime[j]<=n; ++j){
            isnt_prime[i*prime[j]]=1;
            if (i%prime[j]==0) break;
        }
    }
}

int main(){
    scanf("%d%d", &n, &m);
    get_prime(n);
    int t;
    for (int i=0; i<m; ++i){
        scanf("%d", &t);
        if (!isnt_prime[t]) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}

对于当前处理数i,我们将i分解成p1*p2*p3……,当前枚举素数为p[j]。

由于j从小到大枚举,直到i%p[j]==0前,p[j]都是i*p[j]的最小质因数。

在i%p[j]==0后,由于p[j]不是i*p[j]的最小质因数,i*p[j]必然可以被一个更小的质数q筛去。而i*p[j]/q必然会在后面被访问。所以不用遍历。

如何证明复杂度呢?由于2道n区间内的每一个数,都一定只被最小质因数筛掉,所以第二个for循环均摊到n个元素上的时间复杂度是O(1),总时间复杂度就是O(N)。

这是本人对欧拉筛的一点理解,如果有更好的方法或解释,欢迎在评论区评论。。

以上是关于欧拉筛(线性筛)的主要内容,如果未能解决你的问题,请参考以下文章

线性筛素数(欧拉筛)

线性筛素数(欧拉筛)

欧拉筛&&线性筛

线性筛

欧拉筛(线性筛)

欧拉筛线性处理莫比乌斯函数