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

埃氏筛法

时间:2018-08-11 15:45:53      阅读:173      评论:0      收藏:0      [点我收藏+]

标签:开始   algo   pac   class   模板题   mes   turn   names   大于   

埃氏筛法的基本思想:

这个东西的基本思路就是首先把1~n中小于2的数先标记,因为这些数字都不是质数。之后我们依次标记这个里面所有质数的倍数,直到这个质数的平方要大于n的时候,我们就停止这个程序。这样我们剩下没有标记的数就是要求的质数了。没有如果你还不理解的话,我们就来举一个例子:加入我们要求出1~25里面的所有质数,我们可以这么做。首先这个里面的第一个质数是2,所以我们要标记所有大于2的倍数,之后下一个质数就是3,我们就标记所有大于3的倍数,这样做直到6,现在6的平方大于25,就结束程序。、

这个里面还有一个小技巧,就是加入我们知道了当前的质数,我们要怎么知道下一个质数。我们可以发现,加入我们标记了当前质数的所有比它大的倍数之后我们从当前质数开始往下枚举,遇到第一个没有被标记的数就是下一个质数了。

注意:我们在循环变量里尽量使用 register 类型的变量这样可以加快整个程序,防止被卡常,因为 register 类型的变量是放在CPU寄存器里的,这样变量 读取/写入 的速度要比在内存里快很多 至少要快两倍

模板题:

洛谷 [p3912]
是不是想写写看这个算法?这里刚好有一个模板题来测这个算法。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1e8+5;

int n;
bool check[N]; //如果check [i] == false 表示 i 是一个素数  

int main()
{
    scanf("%d",& n);
    
    register int p=2;check[1]=true;
    while(true)
    {
        if(p*p>=n)
            break;
        
        //先标记合数 
        for(register int i=p+p;i<=n;i+=p)
            check[i]=true;
            
        //找到下一个质数 
        for(register int i=p+1;i<=n;i++)
        {
            if(!check[i])
            {
                p=i;
                break;
            }
        }
    }
    
    register int ans=0;
    for(register int i=1;i<=n;i++)
    {
        if(!check[i])
            ans++;
    }
    
    printf("%d\n",ans);
    
    return 0;
}

埃氏筛法

标签:开始   algo   pac   class   模板题   mes   turn   names   大于   

原文地址:https://www.cnblogs.com/lixiao189/p/9459654.html

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