埃式筛法

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;
        }
    }
}
View Code

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

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

(转)

原文地址:https://www.cnblogs.com/16er/p/5158903.html