数论筛法小记
会挖坑,好让复习的时候长脑子。
很多证明只是提两句,因为给自己看,以免复习时没有思路。
以下所有 \(p\) 都是质数,即 \(p\in\mathbb{P}\),同时默认均为正整数。
基础(Base)
唯一分解定理(算术基本定理):
后面默认都分解了。
积性函数:
完全积性函数:
完全积性函数出现的比较少,不过积性函数也较好处理,可以线性筛。
经典的积性函数:
-
\(\varphi\):欧拉函数。有性质 \(\varphi(n)=n\prod{\frac{p_k-1}{p_k}}\) 和 \(n=\sum\limits_{d\mid n}\varphi(d)\)。
第一个考虑 \(\varphi(p^t)\) 的取值,发现是 \(p^{t-1} (p-1)\) 就很好说明。
第二个考虑 \(\frac{1}{n},\frac{2}{n},\dots,\frac{n}{n}\) 这一串数的个数,化成最简分数来算。
-
\(\mu\):莫比乌斯函数。原始定义是 \(\sum\limits_{i=1}^n\mu(i)=[n=1]\)。
根据定义可得:
-
\(\text{d}\) 与 \(\sigma\) 及 \(\sigma_k\):约数个数函数 与 约数和函数 及 除数函数。
其实 \(\text{d}\) 就是 \(\sigma_0\)……
表述可以是:\(\sigma_k(n)=\sum\limits_{d\mid n}d^k\)。
一些比较牛逼的完全积性函数:
- \(\epsilon\)
,依夫瑟洛!:狄利克雷卷积下的单位元,\(\epsilon(n)=[n=1]\)。 - \(\text{I}\):单位函数,\(\text{I}(n)=1\)。
- \(\text{Id}\) 与 \(\text{Id}_k\):就是走个形式,\(\text{Id}_k(n)=n^k\)。
别的先不谈,考虑怎么算积性函数。
简单筛(Sieve base)
计算原理
其实说筛之前应该先看一下积性函数的计算原理。
由于算术基本定理,任意数都可以表为若干个质数的次幂乘积。
因此我们只要分解 \(x\),就可以根据积性函数的性质乘出 \(f(x)\)。
由于分解难,往往是 \(\mathcal{O}(\sqrt{n})\) 的复杂度,当然有一些随机算法能做到更优。
然而另一种思路是主动去凑 \(n\),这在要求出 \(1\sim n\) 的 \(f\) 的值时就会更快。
这样就成了筛法。
线性筛。
埃筛 is too naive。
线性筛使得每个数字只被自己的最小质因子筛一次,过程如下:
Note: This is not pseudocode!
- If i is a prime
- Add i into the P
- For all pri in P
- Calc x=i*p
- if p is a divisor of i
* Calc x by p and i,then break
- else f(x)=f(i)*f(p)
关键步骤在 * 一句,我们需要根据 \(p\) 和 \(i\) 算出 \(x=ip\) 的值,而此时 \(i\) 中已经含有至少一个 \(p\)。
可以使用无脑做法:\(f(x)=f(\frac{i}{p^t})f(p^t)\),显然可知 \(\frac{i}{p^t} \perp p^t\),正确性有保障。
注意像 \(x=p^t\) 这样形式的情况要特别算。
这个基本就是线性筛积性函数的普适做法,感觉其实非常地简单但我当初就是听不懂。
狄利克雷卷积(Dirichlet Convolution)
狄利克雷卷积(以下简称卷积),定义如下:
若 \(h=f*g\),则
卷积满足交换律:\(f*g=g*f\)。
同时满足结合律:\((f*g)*h=f*(g*h)\)。
一些常见的卷积:
- \(\epsilon*f=f\)
- \(\text{I}*\mu=\epsilon\)
- \(\text{Id}_k*\text{I}=\sigma_k\)
- \(\text{I}*\varphi=\text{Id}\)
- \(\text{Id}*\varphi=\mu\)
上面这些都可以拆式子得到。
比较重要的,卷积结合点乘的特殊规律:
\((f\cdot g)*(f\cdot h)=f\cdot(g*h)\),要求 \(f\) 是完全积性函数。
考虑证明:
显然成立。
整除分块(Sqrt Decomposition)
现在补充这个 trick。
考虑一个形如:\(\sum\limits_{i=1}^n f(i)g(\lfloor\frac{n}{i}\rfloor)\) 的式子。
不难发现,\(g(\lfloor\frac{n}{i}\rfloor)\) 这一部分的值在一段内是相同的。
那么能否拆成若干段来加速?
- 对于 \(i\le\sqrt{n}\),\(\lfloor\frac{n}{i}\rfloor\) 的取值只有 \(\mathcal{O}(\sqrt{n})\) 种。
- 对于 \(i>\sqrt{n}\),\(\lfloor\frac{n}{i}\rfloor<\sqrt{n}\),因此取值也只有 \(\mathcal{O}(\sqrt{n})\) 种。
枚举每一段左右端点,取另一函数区间和(可用前缀和相减得到),乘上即可。
然后怎样根据 \(l\) 算出另一端点 \(r\)?
不难发现,由于 \(\lfloor\frac{n}{l}\rfloor=\lfloor\frac{n}{r}\rfloor\),可得 \(r\lfloor\frac{n}{l}\rfloor\le n\)。
然后分完一整段则是 \(r\) 最大,那么由 \(r\le\frac{n}{\lfloor\frac{n}{l}\rfloor}\),可知 \(r=\lfloor\frac{n}{\lfloor\frac{n}{l}\rfloor}\rfloor\)。
代码如下 (放弃了鬼畜的流程表述):
for(int l=1,r;l<=n;l=r+1)
r=(n/(n/l)),ans=(sum[r]-sum[l-1])*func(n/l);
扩展:若存在 \(n\) 和 \(m\) 两个范围,即形如:\(\sum\limits_{i=1}^{\min{n,m}} f(i)g(\lfloor\frac{n}{i}\rfloor)h(\lfloor\frac{m}{i}\rfloor)\),则每一块为:\([i,\min{\lfloor\frac{n}{\lfloor\frac{n}{i}\rfloor}\rfloor,\lfloor\frac{m}{\lfloor\frac{m}{i}\rfloor}\rfloor}]\),且块的数量是 \(\mathcal{O}(\sqrt{n}+\sqrt{m})\) 级别的。
这个东西用处很多,比如在能快速求某一函数前缀和,或 \(\mathcal{O}(n)\) 预处理后回答多次询问等情形。
杜教筛!(Du)
杜教筛用于在亚线性时间内求积性函数前缀和。
思路:构造 \(h=f*g\),其中 \(f\) 是欲求前缀和的函数。
记 \(Sf\) 为 \(f\) 前缀和,写一写:
不难发现形成了递归式,变一下式子即可得到 \(Sf(n)\):
然后运用整除分块,即可直接做。
需要 \(g\) 能快速查单点,\(h\) 能快速算前缀和 (有时或可筛套筛?)。
复杂度我不会证,似乎要用到微积分,CSP 完了学一下。
如果预处理前 \(n^{\frac{2}{3}}\) 项的值,则复杂度是 \(n^{\frac{2}{3}}\) 的;否则为 \(n^{\frac{3}{4}}\)。
不要求是积性函数,能卷就行。
Trick
也许是重点。
这种情况可以把 \(f(d)\) 提到外层求和,然后内层因为顺序无关,而 \(k=\frac{i}{d}\) 遍取 \(1\sim\lfloor\frac{n}{d}\rfloor\) 中所有整数(考虑 \(kd=i,i\le n\),可以解出 \(k\) 的范围),故可化为:
这个推导在直观上很对,但不难发现直观理解出来,枚举的量既有重又有漏。
但是我们考虑 \(p^{t_1}\mid i\) 和 \(p^{t_2}\mid j\) 及 \(p^{t_3}\mid d,d\mid ij\),不妨做这样的钦定:
- 若 \(t_3\le t_1\),钦定全部用 \(i\) 中的 \(p\);此时 \(d_1\) 含有因子 \(p\),\(d_2\) 不含。
- 若 \(t_3>t_1\),钦定用完 \(i\) 中的 \(p\),然后使用 \(j\) 中的 \(t_3-t_1\) 个 \(p\);此时 \(d_2\) 含有因子 \(p\),并强制令 \(d_1\) 不含。
也就是说当 \(d_1\) 不含因子 \(p\) 而 \(d_2\) 含有时,意味着 \(d_1\) 提供 \(i\) 的所有因子 \(p\) 给 \(d\)。
两种情况下都做到了 \(\gcd(d_1,d_2)=1\),同时保证了对于 \(d\) 任意因子 \(p\) 的所有个数方案都可达。
故上式正确,同时也可解释为何在算约数和时不能直接套用此法。