zoukankan      html  css  js  c++  java
  • 进阶必备:素数筛法(欧拉,埃氏筛法)

    筛选素数其实有两种比较高效的算法可以提供选用,分别是:Eratosthenes筛选法与欧拉筛选法。但是欧拉算法的普适性比较高,所以这里就只介绍欧拉函数的算法。
    筛选的范围较小的话,欧拉算法,数据较大,埃氏筛法,所以埃氏筛法一定要掌握,以后可以统一用埃氏筛法
    【埃氏筛法】

    const int maxn=10000005;
    int prime[maxn];
    int vis[maxn];
    int cnt = 0;
    void sieve()//返回n以内的素数
    {
        cnt=0;
        for(int i=0;i<=maxn;i++)
            vis[i]=1;
        vis[0]=vis[1]=0;
        for(int i=2;i<=maxn;i++)
            if(vis[i])
            {
                prime[cnt++]=i;
                for(int j=2*i;j<=maxn;j+=i)
                    vis[j]=0;
            }
    }

    筛选10000000以内的素数,埃氏筛法的平均时间是0.756秒,而欧拉算法达到了2.2秒多,所以算法的复杂度埃氏筛法远远优于欧拉。
    还有一种筛选法的速度比埃氏筛法还要快一些,它的10000000以内的时间为0.721秒。代码贴上来作为参考:

    const int maxn=10000005;
    int prime[maxn];
    int vis[maxn];
    int check[maxn];
    int cnt = 0;
    void init()
    {    
        int cnt=0;
        check[0]=check[1]=1;
        for(int i=2;i<maxn;i++)
        {
            if(!check[i])
            {
                prime[cnt++]=i;
                vis[i]=1;
            }
            for(int j=0;j<cnt;j++)
            {
                if(prime[j]*i>=maxn) break;
                check[i*prime[j]]=1;
                if(i%prime[j]==0) break;
    
            }
        }
    }

    以上两种算法,执行完毕之后,vis数组里面的如果为1,表示为素数,为0则为合数。prime数组里面保存的则是素数集,cnt表示素数的个数。还有重要的一点就是对于卡时间的题,注意不要使用cin,cout这类的输入输出了,不然时间会爆掉,比如下面牛客网的这题,如果不用scanf还有printf的话,就是过不了的,所以养成好习惯的话,以后应当减少cin,cout的使用,实在无法避免使用的话,可以试试加上ios::sync_with_stdio(false); (因为即使加上这句话,cin/cout体系还是没有scanf/printf快)
    【题源】牛客网

    欧拉筛法因为不具有普适性,时间优化不够好,所以在这里不贴上来了,有兴趣的读者可以自行百度。

    2019/4/23 二改

  • 相关阅读:
    Java内存模型深度解析:final
    Java内存模型深度解析:总结
    打印流
    Properties
    进制间的转换
    JAVA IO
    001课-java_web开发入门
    openssl生成https证书 (转)
    PostgreSQL中COUNT的各条件下(1亿条数据)例子
    6个原因说服你选择PostgreSQL9.6
  • 原文地址:https://www.cnblogs.com/myxdashuaige/p/8890712.html
Copyright © 2011-2022 走看看