码迷,mamicode.com
首页 > 其他好文 > 详细

欧拉筛(线性筛)

时间:2017-08-01 21:40:50      阅读:2515      评论:0      收藏:0      [点我收藏+]

标签:++   for循环   顺序   can   turn   不用   元素   get   log   

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

欧拉筛是一种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)。

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

欧拉筛(线性筛)

标签:++   for循环   顺序   can   turn   不用   元素   get   log   

原文地址:http://www.cnblogs.com/MyNameIsPc/p/7270657.html

(1)
(4)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!