一些时空复杂度

一些时空复杂度

个人用于积累一些关于复杂度的知识的。理论向是一些关于复杂度的理论,实践向是积累一些常用的复杂度。

理论向

关于 O、Θ、Ω 符号

大部分 Oier 似乎都不大懂这一部分。为了后面方便叙述和严谨性,还是写一下。

以下的 \(f(n)\)\(g(n)\) 为两个非负函数。且在实际的复杂度分析中,一般\(f(n)\)\(g(n)\) 单调不降(但在此处的定义无需保证这点)。

  1. \(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)\)。(渐进准确界);
  2. \(f(n) = \mathcal{O}(g(n))\),当且仅当 \(\exist c,n_0 \gt 0,\forall n \ge n_0, f(n) \le c \cdot g(n)\)。(渐进上界);
  3. \(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 圈更常见的表述:

\[T(x) = \begin{cases} \mathcal{O}(x^ {\log _b a}) , x ^ {\log _b a} > f(x) \\ \mathcal{O}(x^ {\log _b a} \log x) , x ^ {\log _b a} = f(x)\\ \mathcal{O}(f(x)) ,x^{\log _b a} < f(x) \end{cases} \]

其中 \(=\) 表示同级,\(<\)\(>\) 表示多项式的大于或小于。

现在给出更加准确的定义。

\[T(n) = \begin{cases} \Theta (n ^{\log _b a }),f(n)= \mathcal{O}(n^{\log _b (a) -\epsilon}),\epsilon \gt 0\\ \Theta (n ^ {\log_{b}(a)} \log ^{k+1} n) ,f(n)=\Theta (n^{\log_b a} \log^k n),k \ge 0\\ \Theta(f(n)), f(n)= \Omega(n ^{\log_b (a) + \epsilon}),\epsilon \gt 0 \end{cases} \]

Akra-Bazzi 定理

另一个算递推式复杂度的方法,但更麻烦。

\(f(x)\) 为非负函数,

\[T(n)= \begin{cases} \Theta(1) ,n \le X_0\\ \sum \limits_{i=1}^k a_i \cdot T(b_i n) +f(n) \ ,n \gt X_0 \end{cases} \]

满足

\[\forall 1 \le i \le k,a_i \gt 0,0\lt b_i \lt 1, X_0 \gt \frac{1}{1-b_i},f(n)\text{满足多项式增长条件} \]

什么是多项式增长条件

对于定义在非负实数的函数 \(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)\) 满足多项式增长条件。

\[T(n) = \Theta \left (n^p \left (1+\int _1^n \frac{g(x)}{x^{p+1}} dx\right)\right ) \]

其中 \(p\)\(\sum \limits _{i=1}^k a_i b_i ^p =1\) 的实数根。

证明见这篇文章 知乎 - 从主方法到Akra-Bazzi定理

实践向

整除分块套整除分块

形式化地,欲求

\[\sum_{d=1} ^n f(d) \sum _{k=1} ^{\left\lfloor\frac{n}{d}\right\rfloor} g(k) h(\left\lfloor\frac{n}{dk}\right\rfloor) \]

其中 \(f,g\) 的前缀和和 \(h\)\(\mathcal{O}(1)\) 可求。

\[\left\lfloor\frac{a}{bc}\right\rfloor = \left\lfloor\frac{\lfloor\frac{a}{b}\rfloor}{c}\right\rfloor \]

可以将后面一个和式写成 \(F(\left\lfloor\frac{n}{d}\right\rfloor)\),然后整除分块。

复杂度为 (忽略了向下取整)

\[\begin{aligned} \sum _{d=1} ^{\sqrt{n}} \left(\sqrt {d}+ \sqrt {\frac{n}{d}} \right ) &= \sum _{d=1} ^ {\sqrt n} \sqrt d + \sqrt n \sum _{d=1} ^ {\sqrt n} d^{- \frac{1}{2}} \\& \le \int _1 ^{\sqrt n} x ^{\frac{1}{2}} dx + \sqrt n \int _{1} ^ {\sqrt n} x ^ {- \frac{1}{2}} dx \\ &= \mathcal O(n^{\frac{3}{4}}) + \sqrt n \mathcal O(n^\frac{1}{2}) \\&= \mathcal{O}(n^\frac{3}{4}) \end{aligned}\\ \]

证毕!

埃氏筛

由质数分布可知第 \(i\) 个质数估计为 \(i \ln i\)

故复杂度为

\[\begin{aligned} \sum \frac{n}{p} &=\frac{n}{2}+ n \sum _{i=2} ^{\frac{n}{\ln n}} \frac{1}{i \ln i} \\& \le \frac{n}{2}+n \int _2 ^\frac{n}{\ln n} \frac{1}{x \ln x} dx \\ & =\frac{n}{2}+n \int _2 ^{\ln n - \ln \ln n} \frac{1}{e^r r} d (e ^r) ,(r=\ln x) \\ &=\frac{n}{2}+n \int _2 ^{\ln n - \ln \ln n} \frac{1}{r} dr\\ &= \mathcal O(n\ln\ln n) \end{aligned}\\ \]

替罪羊树维护的 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\)

则复杂度为

\[T(n) = T(\alpha ^2 n) + T(\alpha (1-\alpha) n) + \mathcal O (1) \]

\(p\)\(\alpha ^{2p}+ [\alpha (1-\alpha)]^p = 1\) 的根。

\[\begin{aligned} T(n) &= \mathcal O \left(n ^ p \left(1+\int _{1} ^n \frac{1}{x^{p+1}} dx\right)\right) \end{aligned} \]

过于难分析,所以我们取 \(\alpha\) 具体值试试。

\(\alpha=\frac{3}{5}\),解得 \(p \approx 0.57\)

然后积分

\[\int _{1} ^n {x^{-1.57}} dx < 1 \]

所以 $T(n) \approx \mathcal O(n^{0.57}) $。

在 OI 的数据范围内,\(n^{0.08} \lt 3\),完全可以视为常数。

这也是为什么替罪羊树维护的 K-D Tree 一直被称为复杂度假了,但没人卡掉的原因(至少我没见过)。

对于更一般的情况,先研究一下函数

\[f(x) = \alpha ^{2x} +[\alpha(1 -\alpha)]^x -1 \]

显然函数 \(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)

\[\int _1 ^ n x^{-1-p} dx = -p n ^{-p} +p \lt p \lt 1 \]

则可以得到 $T(n) = \mathcal O (n^p),0.5 \lt p \lt 1 $。

这个 \(p\) 我不知道有没有通式解,但可以代入 \(\alpha\) 解得,在 \((0.5,0.75]\) 的范围内为 \((0.5,0.6763]\),在 OI 中是可以接受的,结合实际情况调参平衡插入复杂度即可。

posted @ 2026-04-05 22:18  MZMTab  阅读(5)  评论(0)    收藏  举报