数论筛法小记

会挖坑,好让复习的时候长脑子。

很多证明只是提两句,因为给自己看,以免复习时没有思路。

以下所有 \(p\) 都是质数,即 \(p\in\mathbb{P}\),同时默认均为正整数。

基础(Base)

唯一分解定理(算术基本定理):

\[\begin{align} \forall n>1,n=\prod\limits_{i=1}^k p_i^{t_i} \end{align} \]

后面默认都分解了。

积性函数:

\[\begin{align} \forall x\perp y,f(xy)=f(x)f(y) \end{align} \]

完全积性函数:

\[\begin{align} \forall x,y\in\N_+,f(xy)=f(x)f(y) \end{align} \]

完全积性函数出现的比较少,不过积性函数也较好处理,可以线性筛。

经典的积性函数:

  • \(\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]\)

    根据定义可得:

\[\mu(x)= \begin{cases} (-1)^k,&\forall p\mid n,p^2 \nmid n\\ 0,&\text{otherwise}. \end{cases} \]

  • \(\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\),则

\[h(n)=\sum\limits_{d\mid n}f(d)g(\frac{n}{d})=\sum\limits_{d\mid n}g(d)f(\frac{n}{d}) \]

卷积满足交换律:\(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\) 是完全积性函数。

考虑证明:

\[\begin{align} (f\cdot g)*(f\cdot h)(n) &=\sum\limits_{d\mid n} (f\cdot g)(d)(f\cdot h)(\frac{n}{d}) \\ &=\sum\limits_{d\mid n} f(d)f(\frac{n}{d})g(d)h(\frac{n}{d}) \\ &=\sum\limits_{d\mid n} f(n)g(d)h(\frac{n}{d}) \\ &=f(n)\sum\limits_{d\mid n} g(d)h(\frac{n}{d}) \\ &=f(n)\cdot(g*h)(n) \end{align} \]

显然成立。

整除分块(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\) 前缀和,写一写:

\[\begin{align} Sh(n)&=\sum\limits_{i=1}^n h(i) \\ &=\sum\limits_{i=1}^n \sum\limits_{d\mid i}g(d)f(\frac{i}{d}) \\ &=\sum\limits_{d=1}^n g(d)\sum\limits_{d\mid i,i\le n}f(\frac{i}{d}) \\ &=\sum\limits_{d=1}^n g(d)\sum\limits_{k=1}^{\lfloor\frac{n}{d}\rfloor}f(k) \\ &=\sum\limits_{d=1}^n g(d)Sf(\lfloor\frac{n}{d}\rfloor) \end{align} \]

不难发现形成了递归式,变一下式子即可得到 \(Sf(n)\)

\[\begin{align} Sh(n)&=\sum\limits_{d=2}^n g(d)Sf(\lfloor\frac{n}{d}\rfloor)+g(1)Sf(n) \\ g(1)Sf(n)&=Sh(n)-\sum\limits_{d=2}^n g(d)Sf(\lfloor\frac{n}{d}\rfloor) \\ Sf(n)&=\frac{Sh(n)-\sum\limits_{d=2}^n g(d)Sf(\lfloor\frac{n}{d}\rfloor)}{g(1)} \end{align} \]

然后运用整除分块,即可直接做。

需要 \(g\) 能快速查单点,\(h\) 能快速算前缀和 (有时或可筛套筛?)

复杂度我不会证,似乎要用到微积分,CSP 完了学一下。

如果预处理前 \(n^{\frac{2}{3}}\) 项的值,则复杂度是 \(n^{\frac{2}{3}}\) 的;否则为 \(n^{\frac{3}{4}}\)

不要求是积性函数,能卷就行。

Trick

也许是重点。


\[\begin{align} &\sum\limits_{i=1}^n\sum\limits_{d\mid i} f(d)g(\frac{i}{d}) \\ &=\sum\limits_{d=1}^n\sum\limits_{d\mid i,i\le n} f(d)g(\frac{i}{d}) \\ \end{align} \]

这种情况可以把 \(f(d)\) 提到外层求和,然后内层因为顺序无关,而 \(k=\frac{i}{d}\) 遍取 \(1\sim\lfloor\frac{n}{d}\rfloor\) 中所有整数(考虑 \(kd=i,i\le n\),可以解出 \(k\) 的范围),故可化为:

\[\begin{align} &=\sum\limits_{d=1}^n f(d)\sum\limits_{k=1}^{\lfloor\frac{n}{d}\rfloor}g(k) \end{align} \]


\[\begin{align} \sum\limits_{i=1}^n\sum\limits_{j=1}^n \sigma_0(ij) \\ &=\sum\limits_{i=1}^n\sum\limits_{j=1}^n\sum\limits_{d_1\mid i,d_1\le n}\sum\limits_{d_2\mid j,d_2\le n} [\gcd(d_1,d_2)=1] \end{align} \]

这个推导在直观上很对,但不难发现直观理解出来,枚举的量既有重又有漏。

但是我们考虑 \(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\) 的所有个数方案都可达。

故上式正确,同时也可解释为何在算约数和时不能直接套用此法。

posted @ 2023-10-13 23:37  LQ636721  阅读(51)  评论(0)    收藏  举报