其实不少高等数学 / 数学分析教材在讲解无穷小的比较时已经相当严谨地介绍过大 O、小 O 记号,然而各种历史习惯记法的符号滥用(abuse of notation)[1] 直到现在都让笔者头疼. These notations seem to be innocent, but can be catastrophic without careful manipulation. For example,
Knuth 在《具体数学》里举出的例子[2]. “
没看出有啥问题,对吧?笔者在写作此文时犯了同样的错误. 请注意,大 O 记号的作用对象是函数,
这种错误的出现是在所难免的,我们太习惯用
然而大家还是喜欢写
但上述命题从结论上是正确的. 正确的推导过程应为
第一步是直接由大 O 记号的定义得到的结果.
Wikipedia[3] 中有一张详尽的表格介绍了各种渐进符号的定义,OI Wiki[4] 上也有极好的讲解,尚不熟练的读者可以参考. 有兴趣仔细研究的读者可以参考《具体数学》第九章[2]、Wikipedia 及其 reference(个人推荐 Knuth 关于
调和级数的部分和
当
当
当
约数函数(Divisor Function,也可称为除数函数、因数函数)是与
Definition 1 (约数函数)
当
Example 1 估计
也就是估计
事实上进一步可以证明
Example 2 估计
即估计
显然,这比
进一步利用此技巧和
Example 3 估计
遗憾的是,对此前缀和做差分并不能得到
现在引入一个重要放缩技巧,其在后续估计中屡试不爽.
Proposition 1
显然,右式比左式多算了
Proposition 2
Example 4 估计
可以证明用 Proposition 2 不会得到更优的结果.
我们发现了一个有趣的事实:
Example 5 估计
用 Proposition 2 和
我们得到了一个相当优秀的渐进上界. 值得关注的是:
另外,如果只使用 Proposition 1 ,
约数函数更复杂的上限与渐进估计可参考 Wikipedia[7].
也被称为数论分块. 求
方便起见,后文记
将 Proposition 2 加强,我们有如下通用放缩:
Proposition 3
LHS 成立的关键在于
注意到 Proposition 2 是 Example 5 证明的核心,而 Proposition 3 是 Proposition 2 的加强版,故仿造 Example 5 的证明,我们有
Example 6 令
现在可以对嵌套整除分块
我们还可以进一步归纳. 假定
因此
杜教筛可以以低于线性的时间复杂度求解某些数论函数的前缀和. 其思路并不复杂. 设
故若
下面分析算法的复杂度. 注意到
但我们还可以做得更好——考虑先用
Proposition 4
特别的,当
故用 Proposition 4 ,当
总时间复杂度
为最小化时间复杂度,取
这部分的时间复杂度证明主要参考了文章[11].
我们指出,无平方因子数有如下计数公式
朴素实现复杂度为
二是实现方案. 这里也直接给出:
=sqrt(N);
ll sqrtN=0;
ll ansfor(ll l=1,r,d;l<=sqrtN;l=r+1){
=N/(l*l),r=sqrt(N/d);
d+=(S_mu(r)-S_mu(l-1))*d;
ans}
最后是算法时间复杂度分析. 普通的
Proposition 5
因此算法递归部分时间复杂度可估计为
这估计并不算优秀. 传言存在