数论 Part:整数分块及其应用
\text{定义}
整数分块是用于快速计算下取整的求和式的一种算法,可以将形如以下形式的求和从
\text{一些例子}
\text{例 1}
例 1:给定正整数
n ,求出以下和式的值。\sum_{i=1}^{n}\left\lfloor\frac{n}{i}\right\rfloor
这是整数分块最基本的形式。
引理 1:给定正整数
n ,对于任意的正整数i\leq n ,\left\lfloor\frac{n}{i}\right\rfloor 至多只有2\sqrt{n} 种取值。证明:当
1\leq i\leq\sqrt{n} 时,显然至多有\sqrt{n} 种取值。当\sqrt{n}<i\leq n 时,显然有\left\lfloor\frac{n}{i}\right\rfloor\leq \sqrt{n} ,故也至多有\sqrt{n} 种取值。综上至多有2\sqrt{n} 种取值。
另一件显而易见的事情是:
引理 2:给定正整数
n ,若一个块的左端点是l ,则其右端点为\left\lfloor\frac{n}{\left\lfloor\frac{n}{l}\right\rfloor}\right\rfloor 。证明:为了便于书写,记
k=\left\lfloor\frac{n}{l}\right\rfloor ,则有k\leq\frac{n}{l} 。显然任意在块中的i 都有\left\lfloor\frac{n}{i}\right\rfloor=k ,则有任意在块中的i 都有\left\lfloor\frac{n}{k}\right\rfloor\geq\left\lfloor\frac{n}{\frac{n}{i}}\right\rfloor=i ,即i 的上界为\left\lfloor\frac{n}{k}\right\rfloor 。
所以对于这一个和式,可以使用一个左端点指针,求出对应块的右端点然后
cin >> n;
for (int l = 1, r; l <= n; l = r + 1) {
r = n / (n / i);
Sum += (n / i) * (r - l + 1);
}
因为我们是依照
\text{例 2}
给定正整数
n ,求出以下和式:\sum_{i=1}^n i\left\lfloor\frac{n}{i}\right\rfloor.
与前一例相比,求和的东西多了一个与
我们一样对后面的向下取整进行整数分块后,若当前块左端点为
for (int l = 1, r; l <= n; l = r + 1) {
r = n / (n / i);
Sum += (l + r) * (r - l + 1) / 2 * (k / i);
}
或
for (int i = 1; i <= n; i ++) Pre[i] = Pre[i - 1] + i;
for (int l = 1, r; l <= n; l = r + 1) {
r = n / (n / i);
Sum += (Pre[r] - Pre[l - 1]) * (k / i);
}
更一般地,对于后面这一种写法,可发现将算法的时间复杂度的瓶颈由求和式转化为了求前缀和,也就是说,关键在于能否
\text{习题}
\text{P2261 [CQOI2007] 余数求和}
根据取模的性质,可以得到
显然与例 2 形式基本一致,尽管
\text{P3935 Calculating}
根据一些数论基础知识可发现,
题目所求和式可以拆分为两个自
故有:
与例
\text{P2424 约数和}
与上题类似,有:
同样地,使用前缀和作差,定义
与例 2 形式相同,输出答案为