整除分块
题外话
一开始是在写洛谷月赛题的,后来发现需要用到整除分块,然后发现这东西似乎在莫比乌斯反演中会用到?所以就突然决定要学莫比鸟斯反演。
[CQOI2007]余数求和
先来康康这道例题:
给出正整数 \(n\) 和 \(k\),请计算
\[G(n, k) = \sum_{i = 1}^n k \bmod i
\]
其中 \(k\bmod i\) 表示 \(k\) 除以 \(i\) 的余数。\(1 \leq n, k \leq 10^9\)
直接算肯定是布星的,先来稍微将柿子变换亿下:
\[G(n, k) = \sum_{i = 1}^n k \bmod i = \sum_{i=1}^{n} k - i * \lfloor \frac{n}{i} \rfloor = n * k - \sum_{i=1}^{n} i * \lfloor \frac{n}{i} \rfloor
\]
这样就转变成了计算 \(\sum \limits_{i=1}^{n} i * \lfloor \frac{n}{i} \rfloor\)
整除分块
\[\sum \limits_{i=1}^{n} \lfloor \frac{n}{i} \rfloor
\]
可以发现上面这个式子中有很多连续的块的取值都是一样的,所以我们可以一次性将整块的信息处理出来,即:
对于任意一个 \(i\),我们需要找到一个最大的 \(j\),使得 \(\lfloor \frac{n}{i} \rfloor \le \lfloor \frac{n}{j} \rfloor\),而 \(j = \lfloor \frac{n}{\lfloor \frac{n}{i} \rfloor} \rfloor\)。
略证:
\[\begin{split}
&\lfloor \frac{n}{i} \rfloor \le \frac{n}{i} \\
&\implies \lfloor \frac{n}{\lfloor \frac{n}{i} \rfloor} \rfloor \ge \lfloor \frac{n}{\frac{n}{i}} \rfloor = \lfloor i \rfloor = i \\
&\implies i \le \lfloor \frac{n}{\lfloor \frac{n}{i} \rfloor} \rfloor
\end{split}
\]
即
\[j = \lfloor \frac{n}{\lfloor \frac{n}{i} \rfloor} \rfloor
\]
#include <bits/stdc++.h>
using namespace std;
int N, ans;
int main() {
cin >> N;
for (int l = 1, r; l <= N; l = r + 1) {
r = N / (N / l);
ans += (r - l + 1) * (N / l);
cout << l << " " << r << " " << ans << endl;
}
cout << ans << endl;
return 0;
}
既然选择了远方,便只顾风雨兼程。