今天在做《Concrete Mathematics and Its Applications》的时候,注意到了一个叫做Eratosthenes筛选法的筛选素数的方法,通过对它的学习可谓是对算法复杂度有了一个进一步的理解。
0.Eratosthenes筛法
- 问题背景:在2~n的整数集合中找出所有的素数
- 算法描述:第一步先把所有2的倍数全部去掉,接下来的每一步都把剩下数中,最小的数的倍数都去掉,直到没有合数为止。
- 进一步分析——每次去掉的都是什么数?根据素数的定义,被去掉的必然是合数。由此也可以推出,每次挑选的最小的数必然是素数。
- 进一步分析——什么时候终止?先给出结论,当外层循环变量 i = ⌈ n ⌉ i = \lceil \sqrt n \rceil i=⌈n⌉时停止。因为这时候所有比它小的质数的倍数都已经被去掉。因此要筛去的第一个数必然是他自身的平方,即 i 2 i^2 i2。而此时的结果已经超出了我们的范围,因此循坏结束
- 动画示例:
这个算法的时间复杂度是 O ( n l o g l o g n ) O(\sqrt n loglogn) O(nloglogn),下面我一步一步给出这个结论的推导。
1. Lemma
Newton 幂级数 l n ( x + 1 x ) = 1 x − 1 2 x 2 + 1 3 x 3 − . . . ln(\frac{x+1}{x}) = \frac{1}{x} - \frac{1}{2x^2}+\frac{1}{3x^3} - ... ln(xx+1)=x1−2x21+3x31−...
Proof.
注意到 l n ( x + 1 x ) = l n ( 1 + 1 x ) ln(\frac{x+1}{x}) = ln(1+\frac{1}{x}) ln(xx+1)=ln(1+x1)
设 t = 1 x t=\frac{1}{x} t=x1, 求 l n ( 1 + t ) ln(1+t) ln(1+t)的Maclaurin展开,得到
l n ( 1 + t ) = t