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

线性筛法

时间:2017-08-20 22:43:25      阅读:419      评论:0      收藏:0      [点我收藏+]

标签:线性   i++   它的   style   证明   问题   name   color   oid   

关于线性筛法

线性是指O(n)内筛掉所有合数,还有一种方法叫埃氏筛法,我先证明埃氏筛法效率低,也就是会有重复。

证明如下:

埃氏筛法的原理是找到一个素数后,它的1~n倍就会被筛掉,任何一个合数都可以被拆成一个质数*合数的形式,我们对每一个质数对应的可能的(合)数都枚举了,这就保证了所有可能的合数都被筛掉了。为什么不是最优呢?问题出在那个质数上,对于一个合数m,m=h*P,P是质数且P>m的最小质因数,那么m也可以表示为m=H*p,(H是个比h大的合数,p是m的最小质因数),这样我们在枚举p的倍数时,m就被筛掉了,而在枚举P的倍数时,m又被筛掉了一次,造成效率浪费。

怎办呢?--------线性筛法

我们在枚举倍数时,保证当前质数不能整除这个倍数就好了,也就是p是m的p,这样我们在最优性的条件下,对每一个质数,它所有对应的倍数,都被枚举到,也就保证了可行性。

代码如下:

#include<bits/stdc++.h>
using namespace std;
int n,cnt;
int prime[100000];
bool vis[100000];

void Euler()
{
    for(int i=2;i<=n;i++)
    {
        if(!vis[i]) prime[++cnt]=i;
        for(int j=1;j<=cnt&&i*prime[j]<=n;j++)
        {
            vis[i*prime[j]]=1;
            if(i%prime[j]==0)
            break;
        }
    }
}

int main()
{
  cin>>n;
  Euler();
  for(int i=1;i<=cnt;i++)
  cout<<prime[i]<< ;
  return 0;
}

里面关键就是那个break,如果不break,就是再往大里枚举,那么以后枚举到的质数,一定不是最小质数,因为它都比当前质数大了,怎么可能最小,最小也只可能是当前的质数,从而实现了优化。

线性筛法

标签:线性   i++   它的   style   证明   问题   name   color   oid   

原文地址:http://www.cnblogs.com/war1111/p/7401426.html

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