素数筛选以及优化分析

素数筛选法的思想:对于不超过N的每个正整数,删除2P,3P,4P……,当处理完所有数之后,还没有被删除的就是素数。



按照上述思想写成的简单筛选法代码如下:

memset(vis,o,sizeof(vis));  
for(int i=2;i<N;i++)  
for(int j=i*2;j<=N;j+=i) vis[j]=1;  
//用vis数组存储数j是否被删除的信息。 

下面我们想想如何改进:

1.由唯一分解定理:每个正整数可以写成n=a1^p1*a2^p2……(其中a1,a2是质数)

改进代码:

memset(vis,0,sizeof(vis));  
for(int i=2;i*i<=m;i++) if(!vis[i])//判断i是质数,  
for(int j=i*i;j<=n;j+=i) vis[j]=1;//直接从i*i开始 

这个改进了的代码也会有重复筛选的情况存在,比如数16,81等


下面给出最优的欧拉筛法,真正的o(n)复杂度

    const int N=1000000+5;  
    int check[N],prime[N];  
      
    memset(prime,0,sizeof(prime));  
    memset(check,0,sizeof(check));  
    int ptot=0;  
    for(int i=2;i<=n;i++){  
       if(!check[i]) prime[ptot++]=i;  
       for(int j=0;j<ptot;j++){  
       if(prime[j]*i>n) break;  
       check[prime[j]*i)=1;  
       if(i%prime[j]==0) break;//区别第二个代码的一步  
       }  
    }   



欧拉筛法和第二个代码 思想类似,只是多了关键了一步,“ifi%prime[j]==0) break;"

为什么要这样做呢?

分析第二个代码,它极大地避免了重复的筛选,它的外层筛选只选取质数,内层循环避免了2*3和3*2的这种重复筛选

但是像24这种既可以分解为2*12,又可以分解为3*8的来说,第二个代码就没有避免对24的重复筛选。


下面给出欧拉筛法里面关键一步的原理证明

设合数n的最小质因数为p,另一个比它大的质因数为p1,设n=p*m=p1*m1;因为p和p1互质,则p|m1;另外可以知道m1<m,故若在i为m1的时候对n筛选一次的话,那么在后面i为m的时候,又会对n筛选一次,所以需要判断m1%p==0;(可以证明起冲要性)这样就会只在i为m的时候对n进行筛选,实现了对每一个数只筛选一次。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值