Eratosthenes筛法时间复杂度的数学分析
此文献给那些对于算法背后的数学知识真正热爱的人,共勉
bool notPrime[maxn];
void init() {
memset(notPrime, false, sizeof notPrime);
notPrime[0] = notPrime[1] = true;
for (int i = 2; i <= n; i++)
for (int j = i*2; j <= n; j += i)
notPrime[j] = true;
}
※注意:代码中内层循环的写法和进入的对象,对于外层循环的每一个 i 都进入了内层循环处理了,内层循环是从 2*i 开始的不是 i*i ,并不是线性筛的最终状态,本文的主要目的是在于分析上面代码的时间复杂度。
时间复杂度的数学分析
外层循环为 n ,当外层循环锁定一个数时,设为 i ,那么内层的循环次数为
⌊
n
i
⌋
−
1
<
n
i
\lfloor \frac{n}{i} \rfloor - 1 < \frac{n}{i}
⌊in⌋−1<in
那么循环总数即为
n
2
+
n
3
+
⋯
+
n
n
\frac{n}{2} + \frac{n}{3} + \cdots + \frac{n}{n}
2n+3n+⋯+nn
提取 n 得
n
×
(
1
2
+
1
3
+
⋯
+
1
n
)
n\times (\frac{1}{2} + \frac{1}{3} + \cdots + \frac{1}{n})
n×(21+31+⋯+n1)
根据牛顿(Newton)的幂级数有
l
n
(
x
+
1
x
)
=
1
x
−
1
2
x
2
+
1
3
x
3
−
1
4
x
4
+
1
5
x
5
−
⋯
ln(\frac{x+1}{x}) = \frac{1}{x} - \frac{1}{2x^2} + \frac{1}{3x^3} - \frac{1}{4x^4} + \frac{1}{5x^5} - \cdots
ln(xx+1)=x1−2x21+3x31−4x41+5x51−⋯
可由
l
n
(
1
+
1
x
)
ln(1+\frac{1}{x})
ln(1+x1)在无限远处泰勒展开推出,下式为
l
n
(
1
+
t
)
ln(1+t)
ln(1+t)的麦克劳林展开式
l
n
(
1
+
t
)
=
t
−
t
2
2
+
t
3
3
−
t
4
4
+
t
5
5
−
⋯
ln(1+t)=t-\frac{t^2}{2}+\frac{t^3}{3}-\frac{t^4}{4}+\frac{t^5}{5}-\cdots
ln(1+t)=t−2t2+3t3−4t4+5t5−⋯
将
t
=
1
x
t=\frac1x
t=x1代入
l
n
(
1
+
1
x
)
=
1
x
−
1
2
x
2
+
1
3
x
3
−
1
4
x
4
+
1
5
x
5
−
⋯
ln(1+\frac{1}{x}) = \frac{1}{x} - \frac{1}{2x^2} + \frac{1}{3x^3} - \frac{1}{4x^4} + \frac{1}{5x^5} - \cdots
ln(1+x1)=x1−2x21+3x31−4x41+5x51−⋯
移项得
1
x
=
l
n
x
+
1
x
+
1
2
x
2
−
1
3
x
3
+
1
4
x
4
−
1
5
x
5
+
⋯
\frac{1}{x} = ln\frac{x+1}{x} +\frac{1}{2x^2} - \frac{1}{3x^3} + \frac{1}{4x^4} - \frac{1}{5x^5} + \cdots
x1=lnxx+1+2x21−3x31+4x41−5x51+⋯
分别令
x
=
1
,
2
,
⋯
,
n
x=1, 2, \cdots, n
x=1,2,⋯,n 带入,得
1
1
=
l
n
(
2
)
+
1
2
−
1
3
+
1
4
−
1
5
+
⋯
\frac{1}{1} = ln(2) + \frac12 - \frac13 + \frac14 - \frac15 + \cdots
11=ln(2)+21−31+41−51+⋯
1
2
=
l
n
(
3
2
)
+
1
2
×
4
−
1
3
×
8
+
1
4
×
16
−
1
5
×
32
+
⋯
\frac12 = ln(\frac32) + \frac{1}{2\times 4} - \frac{1}{3\times 8} + \frac{1}{4\times 16} - \frac{1}{5\times 32} + \cdots
21=ln(23)+2×41−3×81+4×161−5×321+⋯
⋮
\vdots
⋮
1
n
=
l
n
(
n
+
1
n
)
+
1
2
×
n
2
−
1
3
×
n
3
+
1
4
×
n
4
−
1
5
×
n
5
+
⋯
\frac{1}{n} = ln(\frac{n+1}{n}) + \frac{1}{2\times n^2} - \frac{1}{3\times n^3} + \frac{1}{4\times n^4} - \frac{1}{5\times n^5} + \cdots
n1=ln(nn+1)+2×n21−3×n31+4×n41−5×n51+⋯
把这 n 个式子加和,整理得
1
+
1
2
+
1
3
+
⋯
+
1
n
=
l
n
(
n
+
1
)
+
1
2
(
1
+
1
4
+
1
9
+
⋯
+
1
n
2
)
−
1
3
(
1
+
1
8
+
1
27
+
⋯
+
1
n
3
)
+
⋯
1 + \frac{1}{2} + \frac{1}{3} + \cdots + \frac{1}{n} = ln(n+1) + \frac12(1+\frac14+\frac19+\cdots +\frac{1}{n^2}) -\frac13(1+\frac18 + \frac1{27}+\cdots + \frac{1}{n^3}) + \cdots
1+21+31+⋯+n1=ln(n+1)+21(1+41+91+⋯+n21)−31(1+81+271+⋯+n31)+⋯
后面那一串是收敛的,设为
γ
\gamma
γ ,则原式为
1
+
1
2
+
1
3
+
⋯
+
1
n
=
l
n
(
n
+
1
)
+
γ
1 + \frac{1}{2} + \frac{1}{3} + \cdots + \frac{1}{n} = ln(n+1) + \gamma
1+21+31+⋯+n1=ln(n+1)+γ
欧拉近似地计算了
γ
\gamma
γ 的值,约为 0.577218 ,这就是欧拉常数
常数项减少并不影响数列的敛散性,当然也可以直接理解为将左侧的第一项移向到右边合并进常数项之中
1
2
+
1
3
+
⋯
+
1
n
=
l
n
(
n
+
1
)
+
C
\frac{1}{2} + \frac{1}{3} + \cdots + \frac{1}{n} = ln(n+1) + C
21+31+⋯+n1=ln(n+1)+C
所以一开始的那个循环的总式用大O表示法可以如此表示
n
2
+
n
3
+
⋯
+
n
n
=
n
×
(
1
2
+
1
3
+
⋯
+
1
n
)
=
O
(
n
l
o
g
n
)
\frac{n}{2} + \frac{n}{3} + \cdots + \frac{n}{n} = n\times (\frac{1}{2} + \frac{1}{3} + \cdots + \frac{1}{n}) = O(n\,log\,n)
2n+3n+⋯+nn=n×(21+31+⋯+n1)=O(nlogn)
注:这里时间复杂度的大O表示法中所展现的 l o g n log\,n logn 仅表示为对数级的数量级,一般认为以 2 为底,但并不做严格限制,所以上式中的 l n n ln\,n lnn 在这里直接表示为 l o g n log\,n logn。
所以 Eratosthenes 筛法 的时间复杂度为 O ( n l o g n ) O(n\,log\,n) O(nlogn)