埃式筛法

2016.1.25

我们都知道,判断一个数是否为素数可以在O(√n)的时间复杂度内解决。但是如果是要求[1,n]内素数的个数,显然一个一个判断有些慢了。

但我们知道一个显而易见的性质:一个合数的所有质因数都小于这个合数,一个质数没有比它小的质因数。

那么我们可以利用已求得的质因数,来对比他大的合数进行筛除。

具体操作如下:首先我们将2至n内的所有数字写下来。此时2为表中最小数,即为素数,然后将2的倍数全部划去。此时表中剩余最小数字是3,即3是素数,再将表中所有3的倍数划去。将该操作进行下去,每次表中剩余的最小的数即为素数,并将它的倍数都划去。


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20


筛除2的倍数


2


3


-


5


-


7


-


9


-


11


-


13


-


15


-


17


-


19


-


筛除3的倍数


2


3


-


5


-


7


-


-


-


11


-


13


-


-


-


17


-


19


-

代码如下:

int n,prime[1000005],e;
bool is_prime[1000005];//is_prime为0表示为素数
void solve()//素数筛
{
    prime[0]=prime[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(!is_prime[i])
        {
            prime[++e]=i;
            if((long long)i*i>n) continue;//防止爆int
            for(int j=i*i;j<=n;j+=i) is_prime[j]=1;
        }
    }
}

这个筛法的时间复杂度并不显然,看起来像是O(n),在noip一般的数据规模下实测也确实接近线性,但他的时间复杂度其实是O(n loglogn),看起来也就是个常数稍大的线性而已?_?

关于这个奇奇怪怪的时间复杂度的证明,其实蒟蒻的博主并没有看懂但贴在这里,有更好证法的可以告诉我?_?

(转)

时间: 2025-01-02 03:57:20

埃式筛法的相关文章

埃式筛法筛选素数 PAT1013

内容摘要: 明确素数到底是啥数. 埃式筛法是干嘛用的. 利用java实现埃式筛法的思路. 利用埃式筛法解决PAT_1013_B 题. 筛法的改进. 素数(prime number)到底是啥数: 定义: 在大于1的自然数中,除了1和它本身以外不能再被其他数所整除. 实例化定义: 3是素数,因为它不可以被除了"1"以及自身"3"之外的数所整除. 10不是素数,因为它除了"1"以及自身"10"之外,还可以被"2"

python埃式筛法求素数

def _odd_iter(): n = 1 while(True): n = n + 2 yield n def _not_divisable(n): return lambda x : x % n > 0 def primes(): yield 2 it = _odd_iter() while(True): n = next(it) yield n it = filter(_not_divisable(n), it) for n in primes(): if n < 1000: prin

埃氏筛法(快速筛选n以内素数的个数)

给你一个数n,请问n以内有多少个素数?(n <= 10e7) 一般来说,要是对一个整数进行素数判断,首先想到的是写个函数判断是否为素数,然后调用这个函数,时间复杂度为O(n^(½)),但是要求n以内的素数就略显吃力了. 要是求n以内的素数个数的话,可以用埃式筛选.预处理一下. 先看下面的代码: 1 /* 2 |埃式筛法| 3 |快速筛选素数| |15-7-26| 4 */ 5 #include <iostream> 6 #include <cstdio> 7 using na

埃氏筛法(素数筛)

埃式筛法:给定一个正整数n(n<=10^6),问n以内有多少个素数? 做法:做法其实很简单,首先将2到n范围内的整数写下来,其中2是最小的素数.将表中所有的2的倍数划去,表中剩下的最小的数字就是3,他不能被更小的数整除,所以3是素数.再将表中所有的3的倍数划去……以此类推,如果表中剩余的最小的数是m,那么m就是素数.然后将表中所有m的倍数划去,像这样反复操作,就能依次枚举n以内的素数,这样的时间复杂度是O(nloglogn). 题解:如果要是按照一个一个判断是否是素数然后把ans+1,时间复杂度

埃氏筛法&amp;欧拉筛法

埃氏筛法 /* |埃式筛法| |快速筛选素数| |15-7-26| */ #include <iostream> #include <cstdio> using namespace std; const int SIZE = 1e7; int prime[SIZE]; // 第i个素数 bool is_prime[SIZE]; //true表示i是素数 int slove(int n) { int p = 0; for(int i = 0; i <= n; i++) is_p

分拆素数和 埃氏筛法

分拆素数和 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 2098 Description 把一个偶数拆成两个不同素数的和,有几种拆法呢? Input 输入包含一些正的偶数,其值不会超过10000,个数不会超过500,若遇0,则结束. Output 对应每个偶数,输出其拆成不同素数的个数,每个结果占一行. Sample Input 30

埃氏筛法

埃氏筛法,理解起来很好理解,就是在1~n这n个连续的数里面开始筛出合数,知道剩下全部为素数,大致流程如下: 第一步:能够确定1不是素数,所以将1筛出,剩下从2开始的数列 第二步:找到2为第一个素数,那么遍历这个数列,将2的倍数筛出,形成一个新的数列 第三步:找到下一个素数 x,此时 x = 3,那么再次遍历这个数列,筛出 x 的倍数,剩下的数再次形成一个新的数列 第四步:重复第三步,直到将所有合数筛出 代码如下: #include <iostream> #include <cstring

素数的快速筛选(埃氏筛法)

要枚举n以内的素数,可以用埃氏筛法.这是一个与辗转相除法一样古老的算法. 首先,将2到n范围内的所有整数写下来.其中最小的数字2是素数.将表中所有2的倍数都划去.表中剩余的最小数字是3,它不能被更小的数整除,所以是素数.再将表中所有3的倍数全都划去.依次类推,如果表中剩余的最小数字是m时,m就是素数.然后将表中所有m的倍数全部划去.像这样反复操作,就能依次枚举n以内的素数. int prime[maxn];//第i个素数 bool is_prime[maxn];//is_prime[i]为tru

埃氏筛法之素数

原理: 首先将2~n个数记录下来,2作为最小素数,所以2的倍数不是素数,从记录中划去,扫一遍之后,将3作为最小素数,3的倍数划去,如此下去,求出所有素数.如表格所示: 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 2 3 - 5 - 7 - 9 - 11 - 13 - 15 - 17 - 19 - 2 3 - 5 - 7 - - - 11 - 13 - - - 17 - 19 - 代码: 判断是否是素数: bool is_prime(int n