整除分块

题外话

一开始是在写洛谷月赛题的,后来发现需要用到整除分块,然后发现这东西似乎在莫比乌斯反演中会用到?所以就突然决定要学莫比鸟斯反演。

[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;
}
posted @ 2020-06-05 16:02  newbielyx  阅读(164)  评论(0编辑  收藏  举报