好久没写数论题,今天在51nod抓了一道,发现自己早就把杜教筛忘得一干二净啦~ 所以今天我把杜教筛学习笔记整理一下,防止以后再次忘记 =v=
[Warning] 杜教筛复杂度证明我暂时还不会 >_< 我会抓紧时间学的
前置技能
如果你已经了解了以下某些部分的内容,请跳过该部分。
积性函数
\(f\)是一个数论函数,若对于任意两个互质的数\(a\)和\(b\)有\(f(a*b) = f(a)*f(b)\),则称\(f\)是积性函数。
(本文可能用到的)常见积性函数
- \(1(n) = 1\)
- \(Id(n) = n\)
- \(e(n) = [n == 1]\)
- \(d(n)\) 因数个数
- \(\sigma(n)\) 因数之和
- \(\mu(n)\) 莫比乌斯函数
- \(\varphi(n)\) 欧拉函数
狄利克雷卷积
两个数论函数\(f\)和\(g\)对于\(n\)的狄利克雷卷积\((f * g)(n)\)是\(\sum_{d | n}f(d)g(\frac{n}{d})\)。
两个积性函数的狄利克雷卷积也是积性函数(此时\(n\)是传入函数中的参数),即:若\(f\)和\(g\)是积性函数,\(h(n) = \sum_{d | n}f(d)g(\frac{n}{d})\),则\(h\)是积性函数。
常见狄利克雷卷积
- \(\mu * 1 = e\),即\(\sum_{d|n}\mu(d) = [n == 1]\)
- \(\mu * Id = \varphi\),即\(\sum_{d|n}\mu(d)\frac{n}{d} = \varphi(n)\)
- \(\varphi * 1 = Id\),即\(\sum_{d|n}\varphi(d) = n\)
杜教筛
杜教筛是用来在\(O(n^\frac{2}{3})\)时间内求一些积性函数的前缀和的。
假设我们要求前缀和的函数是\(f\),它的前缀和为\(S\), 即\(S(n) = \sum_{i = 1}^{n}f(i)\)。
我们选择一个积性函数\(g\)用来和\(f\)卷一卷。(\(g\)是哪来的?怎么求?……不知道,因题而定,基本靠猜 = =)
然后求一下\(f*g\)的前缀和:
\[\begin{align*} \sum_{i = 1}^{n} (f*g)(i) &= \sum_{i = 1}^{n}\sum_{d|i}g(d)f(\frac{i}{d}) \\&= \sum_{d = 1}^{n}g(d)\sum_{d|i} f(\frac{i}{d}) \\ &= \sum_{d = 1}^ng(d)S(\lfloor\frac{n}{d}\rfloor) \\ &= g(1)S(n) + \sum_{d = 2}^{n}g(d)S(\lfloor\frac{n}{d}\rfloor) \\&= S(n) + \sum_{d = 2}^{n}g(d)S(\lfloor\frac{n}{d}\rfloor) \end{align*}\]
那么移项可得
\[S(n) = \sum_{i = 1}^{n} (f*g)(i) - \sum_{d = 2}^{n}g(d)S(\lfloor\frac{n}{d}\rfloor)\]
如果这个\((f*g)(n)\)的前缀和非常好求的话,\(S(n)\)就可以数论分块(看!那有个\(\lfloor\frac{n}{d}\rfloor\)!)然后递归求解下去了。(这里需要用个哈希表之类的东西记忆化。)
栗子
求\(\varphi\)的前缀和
\(\varphi * 1 = Id\),那么
\[\begin{align*}S(n) &= \sum_{i = 1}^{n} (\varphi*1)(i) - \sum_{d = 2}^{n}g(d)S(\lfloor\frac{n}{d}\rfloor) \\ &= \sum_{i = 1}^{n} i - \sum_{d = 2}^{n}g(d)S(\lfloor\frac{n}{d}\rfloor) \\ &= \frac{n (n + 1)}{2}- \sum_{d = 2}^{n}g(d)S(\lfloor\frac{n}{d}\rfloor) \end{align*}\]
递归求解即可。
我的代码:
#include
#include
#include
#include
#include
#include