• 进阶必备:素数筛法(欧拉,埃氏筛法)


    筛选素数其实有两种比较高效的算法可以提供选用,分别是: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常用api
    常用命令
    mysql常用命令
    特性
    centos ubuntu 软件安装
    WebStorm创建Vue项目记录
    登录oracle官网下载资料账号可以使用(保存)(转)
    java学习之路—JDBC—DBUtils
    Linux从入门到精通(第4章--桌面环境)
    Linux从入门到精通(第2章--Linux安装)
  • 原文地址:https://www.cnblogs.com/myxdashuaige/p/8890712.html
Copyright © 2020-2023  润新知