zoukankan      html  css  js  c++  java
  • 素数筛法

    = =素数是一个很重要的块,所以筛法也是灰常重要的

    首先 是传统筛法

    第一版:

     1 #define MAXN 1000001
     2 bool isprime[MAXN];
     3 long  prime[MAXN];
     4 int cnt;
     5 void getprime()
     6 {
     7     int i,j;
     8     memset(isprime,1,sizeof(isprime));
     9     isprime[0]=isprime[1]=cnt=0;
    10     for(i=2;i*i<MAXN;i++)
    11     {
    12         if(isprime[i])
    13         {
    14             for(j=i*i;j<MAXN;j+=i)
    15             {
    16                 if(isprime[j])
    17                 {
    18                     isprime[j]=false;
    19                 }
    20             }
    21 
    22         }
    23     }
    24     for(i=2;i<MAXN;i++)
    25     {
    26         if(isprime[i])
    27             prime[cnt++]=i;
    28     }
    29 }

    ps:其实我个人感觉这个算法平常的一些题是够用的( ̄ε(# ̄)☆╰╮( ̄▽ ̄///)(快学习!

    第二版:

    #define MAXN 1000001
    bool isprime[MAXN];
    long  prime[MAXN];
    int cnt;
    void getprime()
    {
        int i,j;
        memset(isprime,true,sizeof(isprime));
        isprime[0]=isprime[1]=cnt=0;
        for(i=3;i<MAXN;i++)
            prime[i]=i%2==0?0:1;
    
        for(i=2;i<t;i++)
        {
            if(isprime[i])
            {
                for(j=i*i;j<MAXN;j+=i)
                {
                    if(isprime[j])
                    {
                        isprime[j]=false;
                    }
                }
    
            }
        }
        for(i=2;i<MAXN;i++)
        {
            if(isprime[i])
                prime[cnt++]=i;
        }
    }

    相比于第一版,先去除了2以后的偶数,因为这些偶数根本不可能是素数嘛(~ ̄▽ ̄)~,( ̄ε(# ̄)☆╰(废话

    嗯,容我测试一下时间= =,额……这时间不稳定!(╯‵□′)╯︵┻━┻ 怎么时间还增加了啊喂

    仔细想了想 我们可以把第一版储存素数的数组放入循环,但第二版是不可以的,因为优先判断了偶数和奇数,而且我们可以将i*i<MAXN 判断化为 temp=sqrt(MAXN)+1 ;i<temp 从而避免每次计算i*i 

    ps:将储存数组放入循环后,如果你想得到更大的素数需要修改MAXN的值,当然你也可以将储存数组放在外面,下面的算法也均将储存数组放在循环内,但是对于较大值的MAXN,为了效率,我建议使用线性筛法

    第三版

     1 #define MAXN 1000000
     2 
     3 long cnt,temp=sqrt(MAXN)+1;
     4 bool isprime[MAXN];
     5 long long prime[MAXN];
     6 
     7 void getprime()
     8 {
     9     int i,j;
    10     memset(isprime,1,sizeof(isprime));
    11     isprime[0]=isprime[1]=cnt=0;
    12     for(i=2;i<temp;i++)
    13     {
    14         if(isprime[i])
    15         {
    16             prime[cnt++]=i;
    17             for(j=i*i;j<MAXN;j+=i)
    18             {
    19                 if(isprime[j])
    20                 {
    21                     isprime[j]=false;
    22                 }
    23             }
    24         }
    25     }
    26 }

    嗯,现在我们再来测测时间……,(╯‵□′)╯︵┻━┻,到底怎么测啊不会啊喂!老是不稳定!( ̄ε(# ̄)☆╰╮( ̄▽ ̄///)(学习!

    ----------------------------------------------------------------------------------------------------------------------------------------

    下面我们试试线性筛法

    #define MAXN 1000000
    long cnt;bool isprime[MAXN];
    long long prime[MAXN];
    void x_getprime()
    {
        int i,j;
        memset(isprime,1,sizeof(isprime));
        isprime[0]=isprime[1]=cnt=0;
        for(i=2;i<MAXN;i++)//下面循环考虑了超出的情况,所以可以直接使用MAXN
        {
            if(isprime[i])
                prime[cnt++]=i;//与上面一样将储存素数步骤放入循环
            for(j=0;j<cnt&&i*prime[j]<MAXN;j++)//因为这里for循环判断上下均使用i*prime[j]所以我们不将i*prime[j]储存起来,while可以储存试试
            {    
                isprime[i*prime[j]]=false;
                if(!(i%prime[j]))break;//关键点
            }
        }
    }

    传统的筛法和线性素数筛法的区别是,线性筛法不会筛掉同一个数多次,原因在关键点上下面我们来研究一下线性筛法

    首先,筛掉合数:

    首先对于一个数num 其能写成 p1*p2(素数*素数)形式 则其肯定第一次被筛掉

    若其能 n*p(合数*素数)形式,则其也能写成(p1*p2*……pn)的素数形式,则也筛掉

    其次,不重复:

    从上面的循环我们可以看出i一定大于等于prime[j],当i=prime[j] 时我们就退出循环

    而传统筛法里,6=2*3=3*2是被重复筛掉的,而线性筛法中对于6 我们只进行6=2*3的删除

    嗯,以上是今天的的筛法的学习。

    参考:http://blog.csdn.net/dinosoft/article/details/5829550  

    该网页最后也有一种针对奇数的筛法,但我笔记本快没电了( ̄ε(# ̄)☆╰╮(谁叫你不带电源

    所以回去了再看……嗯现在可以去试试TLE的几道题……

  • 相关阅读:
    第二阶段冲刺--第五天
    git托管代码随笔--运用ssh传输,不用每次提交频繁输入github账号密码
    项目冲刺--第十天
    项目冲刺--第九天
    随堂练习--用例图练习
    项目冲刺--第四天
    第五次个人作业: 案例分析--微软必应词典客户端
    Code.R团队展示
    Android 自定义AlertDialog
    Ubuntu打开系统监视器查看进程&资源等信息
  • 原文地址:https://www.cnblogs.com/byzsxloli/p/5397846.html
Copyright © 2011-2022 走看看