一些时空复杂度
一些时空复杂度
个人用于积累一些关于复杂度的知识的。理论向是一些关于复杂度的理论,实践向是积累一些常用的复杂度。
理论向
关于 O、Θ、Ω 符号
大部分 Oier 似乎都不大懂这一部分。为了后面方便叙述和严谨性,还是写一下。
以下的 \(f(n)\) 和 \(g(n)\) 为两个非负函数。且在实际的复杂度分析中,一般有 \(f(n)\) 和 \(g(n)\) 单调不降(但在此处的定义无需保证这点)。
- 称 \(f(n) = \Theta(g(n))\),当且仅当 \(\exist c_1,c_2,n_0 \gt 0,\forall n \ge n_0,c_1 \cdot g(n) \le f(n) \le c_2 \cdot g(n)\)。(渐进准确界);
- 称 \(f(n) = \mathcal{O}(g(n))\),当且仅当 \(\exist c,n_0 \gt 0,\forall n \ge n_0, f(n) \le c \cdot g(n)\)。(渐进上界);
- 称 \(f(n) = \Omega(g(n))\),当且仅当 \(\exist c,n_0 \gt 0,\forall n \ge n_0, f(n) \ge c \cdot g(n)\)。(渐进下界)。
此外 \(o\) 和 \(\omega\) 表示不可达的上下界。
形式化地:\(f(n) = \mathcal {o}(g(n)) \Leftrightarrow \forall c >0,\exist n_0 \gt 0,\forall n \ge n_0, f(n) \lt c \cdot g(n)\)
\(f(n) = \omega(g(n)) \Leftrightarrow \forall c >0,\exist n_0 \gt 0,\forall n \ge n_0, f(n) \gt c \cdot g(n)\)
值得一提的是由于我们更关心程序运行的上界,所以 \(\mathcal{O}\) 符号比 \(\Theta\) 符号更常用,即使后者为更准确。并且可以发现,分析复杂度下界有时是相当困难的,比如网络流各类算法往往在建模题表现的非常好。
在算法复杂度分析中 \(f(n)\) 常取 \(T(n)\),即算法的运行时间/运行空间/基本操作数/WASM Tick 数。
主定理(Master Theorem)
亦译作主方法。
主要处理形如 \(T(n) = a T(\frac{n}{b}) +f(n),T(1) =\Theta(1)\) 的复杂度处理。
先给一个不那么严谨的表述,这也是在 OI 圈更常见的表述:
其中 \(=\) 表示同级,\(<\) 和 \(>\) 表示多项式的大于或小于。
现在给出更加准确的定义。
Akra-Bazzi 定理
另一个算递推式复杂度的方法,但更麻烦。
设 \(f(x)\) 为非负函数,
满足
什么是多项式增长条件
对于定义在非负实数的函数 \(f(n)\),称 \(f(x)\) 满足多项式增长条件当且仅当 \(\exist c_1,c_2>0,\{b_k\},b_k \in(0,1),\forall x \le 1,u \in [b_x x,x],c_1 f(x) \le g(u) \le c_2 g(x)\)。
该定义等价于 \(|f^\prime(n)| = \mathcal{O}(n^\epsilon),\epsilon \gt 0\)。
特别的,\(a,b\in \mathbb R,f(n)= \mathcal{O}(n^a\log ^b n)\),则 \(f(n)\) 满足多项式增长条件。
则
其中 \(p\) 为 \(\sum \limits _{i=1}^k a_i b_i ^p =1\) 的实数根。
证明见这篇文章 知乎 - 从主方法到Akra-Bazzi定理。
实践向
整除分块套整除分块
形式化地,欲求
其中 \(f,g\) 的前缀和和 \(h\) 在 \(\mathcal{O}(1)\) 可求。
由
可以将后面一个和式写成 \(F(\left\lfloor\frac{n}{d}\right\rfloor)\),然后整除分块。
复杂度为 (忽略了向下取整)
证毕!
埃氏筛
由质数分布可知第 \(i\) 个质数估计为 \(i \ln i\)。
故复杂度为
替罪羊树维护的 K-D Tree
很久以前,基于替罪羊树维护的 K-D Tree 是主流写法,但后来渐渐被认为复杂度假了,比如OI-wiki。
但是,基于 Akra-Bazzi 定理,我们可以证明该方法的复杂度。
我们只考虑 \(K=2\) 的情况。在 OI 中,\(K \gt 2\) 的 K-D Tree 几乎是没有用的。
考虑一个极端情况,每棵树都是恰好满足 \(\alpha\)-高度平衡的,也就是最不平衡的情况。这样,大小为 \(n\) 的树被分为 \(\alpha ^ 2 n,\alpha (1-\alpha) n,(1-\alpha) \alpha n,(1-\alpha)^2 n\)。我们再极端点,每次均进入最大的两个矩形,\(\alpha ^2 n,\alpha (1-\alpha) n\)。
则复杂度为
令 \(p\) 为 \(\alpha ^{2p}+ [\alpha (1-\alpha)]^p = 1\) 的根。
过于难分析,所以我们取 \(\alpha\) 具体值试试。
令 \(\alpha=\frac{3}{5}\),解得 \(p \approx 0.57\)。
然后积分
所以 $T(n) \approx \mathcal O(n^{0.57}) $。
在 OI 的数据范围内,\(n^{0.08} \lt 3\),完全可以视为常数。
这也是为什么替罪羊树维护的 K-D Tree 一直被称为复杂度假了,但没人卡掉的原因(至少我没见过)。
对于更一般的情况,先研究一下函数
显然函数 \(f(x)\) 在 \((0,+\infty)\) 单调递减,由于 \(\frac{1}{2} \lt \alpha \lt 1\)。
而 \(f(0.5) = \alpha + \sqrt {\alpha - \alpha ^2} -1 >0\),\(f(1) = \alpha -1 <0\),所以 \(\frac 1 2 \lt p \lt 1\)。(省略了一些 Dirty Work)
而
则可以得到 $T(n) = \mathcal O (n^p),0.5 \lt p \lt 1 $。
这个 \(p\) 我不知道有没有通式解,但可以代入 \(\alpha\) 解得,在 \((0.5,0.75]\) 的范围内为 \((0.5,0.6763]\),在 OI 中是可以接受的,结合实际情况调参平衡插入复杂度即可。

浙公网安备 33010602011771号