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),看起来也就是个常数稍大的线性而已ಥ_ಥ
关于这个奇奇怪怪的时间复杂度的证明,其实蒟蒻的博主并没有看懂但贴在这里,有更好证法的可以告诉我ಥ_ಥ
(转)