我是算法发明家

以下方便起见,令 p 为质数序列($p_1=2, p_2=3,\dots$),$m(n)$ 为小于 n 的质数个数,$w(n)$ 为小于 n 的非完全合数。

本算法主要是通过递推跳过“完全合数”。完全合数和非完全合数定义如下: 对一个合数 $n$,令 c = c(n) 为最大的整数使 $\prod\limits_{i=1}^cp_i<n$,若存在 $k(1\le k\le c)$,使 $p_k\mid n$,则称 n 为完全合数,否则为不完全合数。

由代码中的递推找到所有质数和非完全合数只需 $O(m + w)(请注意 \displaystyle \sum\limits_{k=1}^\infty\prod\limits_{i=1}^k\dfrac{1}{p_i}<\sum\limits_{k=1}^\infty\dfrac{1}{k(k-1)}=2$)。而之后我们可以通过 O(w) 的时间复杂度来找到所有非完全合数,再用 O(\sqrt{n}+w) 的时间复杂度来排序,然后是 O(m + w) 的输出。

现在此算法时间复杂度为 $O(m + w + \sqrt{n}) = O(\dfrac{n}{\log_2n} = O(m))$,故时间复杂度为 $O(m + w)$。

下证:$\lim\limits_{n\to\infty}m+w=\dfrac{n}{\log_2n}$。

(以下等于号 = 按等价理解)
由定义,$\displaystyle m + w = n \times \prod\limits_{i=1}^m(1-\dfrac{1}{p_i})$。

令 $\displaystyle T = T(n) = \prod\limits_{i=1}^m(1-\dfrac{1}{p_i})$,我们证明 $T < \dfrac{e^2}{\log_2n}\log_2T = \displaystyle \sum\limits_{i=1}^m\log_2(1-dfrac{1}{p_i}),由 \log_2(1-x)$ 的解析性,知它的泰勒级数收敛于它本身,故:

$$\begin{aligned}\log_2T&=\sum\limits_{i=1}^m\sum\limits_{k=1}^\infty\dfrac{1}{kp_i^k}\
&=\sum\limits_{k=1}^\infty\dfrac{1}{k}\sum\limits_{i=1}^m\dfrac{1}{p_i^k}
\end{aligned}$$

我们估计 \displaystyle \sum\limits_{i=1}^m\dfrac{1}{p_i^k} 的量级,显然,对于任意的 $k\ge2$,
$$\begin{aligned}
\sum\limits_{i=1}^m&\le\sum\limits_{i=2}^{m+1}\dfrac{1}{i}\
&<\int_1^{m+1}\dfrac{1}{x^k}\mathrm dx\
&=\dfrac{1}{k-1}(1-\dfrac{1}{(m+1)^{k-1}})\
&<\dfrac{1}{k-1}
\end{aligned}$$

$$\begin{aligned}\log_2T&=\sum\limits_{i=1}^m\sum\limits_{k=1}^\infty\dfrac{1}{kp_i^k}\
&=\sum\limits_{k=1}^\infty\dfrac{1}{k}\sum\limits_{i=1}^m\dfrac{1}{p_i^k}\
&<\sum\limits_{i=1}^m\dfrac{1}{p_i}+1
\end{aligned}$$

$$\begin{aligned}\log_2T&=\sum\limits_{k=1}^\infty\dfrac{1}{k}\sum\limits_{i=1}^m\dfrac{1}{p_i^k}\
&=\sum\limits_{i=1}^m\dfrac{1}{p_i^k}+\theta_n(0<\theta_n<1)
\end{aligned}$$

我们只需估计 $\displaystyle \sum\limits_{i=1}^m\dfrac{1}{p_i},由熟知结论,\displaystyle \sum\limits_{i=1}^m\dfrac{1}{p_i}>\log_2\log_2n-1$,故 $\log_2T<\log_2\log_2n+2$,即 $T<\dfrac{e^2}{\log_2n}$,故 $O(m + w) = O(Tn) = O(\dfrac{n}{\log_2n})$,我们证明了此算法的时间复杂度绝不可能改进,后人只能优化常数(是的,常数非常大),证毕。

3 个赞

@Light 信友队论坛太差了,连这么点 \LaTeX 公式都不支持

3 个赞

洛谷专栏链接

3 个赞

这个常数,除以 \log^2(n) 还是存在的,没有到达 O(n)

3 个赞

@黄子凯1 不是XYD支持的LaTeX太少了,是XYD的判定方式不一样,每个$符号前后都要加空格

3 个赞

注意 \log(n)n=10^8 时,只有 8 左右。再往上 O(n) 跑不到,你常数再优化有什么用呢

3 个赞

你公式炸了@黄子凯

3 个赞

建议在论坛里发帖子的时候看看预览界面,不然会炸的一塌糊涂,比如XYD是不支持独行公式的,只支持行内公式,所以你很多的公式都需要写在行内

3 个赞

而且XYD的论坛实在是太lj了,有一些公式都不支持,很烦,管理大大能不能修一下?

3 个赞

不是哥们我还以为你自己写的呢

3 个赞

对啊

2 个赞

也许不是

1 个赞

emmm 没用啊