数论分块学习笔记
数论分块学习笔记
性质
数论分块用于快速计算含有除法向下取整的和式,即形如 \(\sum_{i=1}^nf(i)g(\lfloor\frac{n}{i}\rfloor)\) 的式子。当预处理出 \(f\) 的前缀和时,数论分块可以在 \(O(\sqrt{n})\) 的时间复杂度下计算上述和式的值。
求解
引理 \(1\):
\(\forall a,b,c\in\mathbb{z},\lfloor\frac{a}{bc}\rfloor=\lfloor\frac{\lfloor\frac{a}{b}\rfloor}{c}\rfloor\)
证明:
不妨设 \(a=kb+r(0\le r<b)\),那么 \(\lfloor\frac{a}{b}\rfloor=k\)。
所以有 \(\lfloor\frac{a}{bc}\rfloor=\lfloor\frac{\frac{a}{b}}{c}\rfloor=\lfloor\frac{k+\frac{r}{b}}{c}\rfloor\)。
因为 \(k\) 是整数,\(r<b\),所以 \(\lfloor\frac{k+\frac{r}{b}}{c}\rfloor=\lfloor\frac{k}{c}\rfloor=\lfloor\frac{\lfloor\frac{a}{b}\rfloor}{c}\rfloor\)。
即 \(\lfloor\frac{a}{bc}\rfloor=\lfloor\frac{\lfloor\frac{a}{b}\rfloor}{c}\rfloor\)。
引理 \(2\):
\(\forall n\in\mathbb{N}_+,|\{\lfloor\frac{n}{d}\rfloor|d\in\mathbb{N}_+,d\le n\}|\le \lfloor2\sqrt{n}\rfloor\)。
证明:
对于 \(d\le\lfloor\sqrt{n}\rfloor\),有 \(\lfloor\frac{n}{d}\rfloor\) 最多有 \(\lfloor\sqrt{n}\rfloor\) 种取值,因为 \(d\) 最多有 \(\lfloor\sqrt{n}\rfloor\) 种取值。
对于 \(d>\lfloor\sqrt{n}\rfloor\),有 \(\lfloor\frac{n}{d}\rfloor\) 最多有 \(\lfloor\sqrt{n}\rfloor\) 种取值,因为 \(\lfloor\frac{n}{d}\rfloor\le\lfloor\sqrt{n}\rfloor\) 。
即 \(\forall n\in\mathbb{N}_+,|\{\lfloor\frac{n}{d}\rfloor|d\in\mathbb{N}_+,d\le n\}|\le \lfloor2\sqrt{n}\rfloor\)。
结论:
对于两个整数 \(n,i\),满足 \(\lfloor\frac{n}{i}\rfloor=\lfloor\frac{n}{j}\rfloor,i\le j\le n\) 的最大的 \(j\) 值为 \(\lfloor\frac{n}{\lfloor\frac{n}{i}\rfloor}\rfloor\)。
证明:
即若存在 \(i\) 使得 \(\lfloor\frac{n}{i}\rfloor=k\),则满足 \(\lfloor\frac{n}{j}\rfloor=k\) 的最大的 \(j=\lfloor\frac{n}{\lfloor\frac{n}{i}\rfloor}\rfloor\)。
若 \(j>\frac{n}{k}\),则 \(\lfloor\frac{n}{j}\rfloor<\lfloor\frac{n}{\frac{n}{k}}\rfloor=\lfloor k\rfloor=k\),所以 \(j\le\frac{n}{k}\),即 \(j\le\lfloor\frac{n}{k}\rfloor\)。有 \(\lfloor\frac{n}{j}\rfloor\ge \lfloor\frac{n}{\frac{n}{k}}\rfloor=\lfloor k\rfloor=k\),若不能取等,则说明没有 \(j\) 使得 \(\lfloor\frac{n}{j}\rfloor=k\),这与存在 \(i\) 使得 \(\lfloor\frac{n}{i}\rfloor=k\) 矛盾,故能够取等,又因为 \(\lfloor\frac{n}{j}\rfloor\) 随 \(j\) 减少而单调不减,所以当 \(j=\lfloor\frac{n}{k}\rfloor\) 时 \(\lfloor\frac{n}{j}\rfloor=k\),所以 \(j\) 的最大值为 \(\lfloor\frac{n}{k}\rfloor=\lfloor\frac{n}{\lfloor\frac{n}{i}\rfloor}\rfloor\)。
如此可以得到以下几个性质:
- \(\lfloor\frac{n}{i}\rfloor\) 的值的个数不超过 \(\lfloor2\sqrt{n}\rfloor\),也就是说,枚举 \(\lfloor\frac{n}{i}\rfloor\) 的时间复杂度是 \(O(\sqrt{n})\)。
- 通过 \(\lfloor\frac{n}{i}\rfloor\),假设使得这个值不变的区间的范围是 \([l,r]\),那么可以在 \(O(1)\) 时间内求解出该区间的最右边,并且 \(r+1\) 一定是下一个区间的最左边。
那么就有以下的代码思路:
考虑当 \(\lfloor\frac{n}{i}\rfloor\) 的值不变时,对于这些项的求和 \(\sum_{i=l}^rf(i)g(\lfloor\frac{n}{i}\rfloor)=g(\lfloor\frac{n}{i}\rfloor)\sum_{i=l}^rf(i)\),显然后半部分可以利用前缀和求出,只需要求出前半部分的值即可。
从 \(l=1\) 开始枚举,每次考虑区间 \([l,\lfloor\frac{n}{\lfloor\frac{n}{l}\rfloor}\rfloor]\) 对答案的贡献,也就是 \(g(\lfloor\frac{n}{l}\rfloor)\sum_{i=l}^{\lfloor\frac{n}{\lfloor\frac{n}{l}\rfloor}\rfloor}f(i)\)。后半部分利用前缀和快速求解,前半部分直接计算即可。
最后令 \(l=\lfloor\frac{n}{\lfloor\frac{n}{l}\rfloor}\rfloor+1\),作为下一个枚举区间的左端点。
显然这样的复杂度是 \(O(\sqrt{n})\) 的。
代码
for(int l=1,r;l<=n;l=r+1){
r=n/(n/l);
ans+=(f[r]-f[l-1])*g[n/l];
}
一般化
特别的,如果在和式中出现了 \(\lfloor\frac{a_1}{i}\rfloor,\lfloor\frac{a_2}{i}\rfloor,\cdots,\lfloor\frac{a_n}{i}\rfloor\) 的多个整除式,需要在每一个区间的右端点中取最小值。
拓展
对于上取整的形式也同时拥有这些性质,但更多的是倒序来讲,也就是对于两个整数 \(n,i\),满足 \(\lfloor\frac{n}{i}\rfloor=\lfloor\frac{n}{j}\rfloor,1\le j\le i\) 的最小的 \(j\) 值为 \(\lfloor\frac{n}{\lfloor\frac{n}{i}\rfloor}\rfloor\)。那么我们可以修改枚举顺序,即先让 \(r\) 取到最大值,接着让 \(l\) 取到对应左端点后,下一次令 \(r=l-1\) 即可,一般化也同样适用。