其他分享
首页 > 其他分享> > 整除分块

整除分块

作者:互联网

解决如下问题:给定 \(n\),求

\[\sum \limits_{i=1}^n \lfloor\cfrac{n}{i}\rfloor \]

考虑画出 \(\cfrac{n}{i}\) 的函数图像,并将 \(\lfloor\cfrac{n}{i}\rfloor\) 相等的区间用颜色块表示出来:(取 \(n=7\))
image

发现虽然 \(n=7\),但是只有 \(4\) 个带整数的块。
考虑

\[\sum \limits_{i=1}^n \lfloor\cfrac{n}{i}\rfloor=\sum \limits_{(l,r)} (r-l+1) \times\lfloor\cfrac{n}{l}\rfloor \]

其中 \((l,r)\) 是块的左右端点。怎么求?对于整数 \(i\),其块的右端点为: \(\lfloor\cfrac{n}{\lfloor\frac{n}{i}\rfloor}\rfloor\)。
为什么呢?(举个例子: \(i=5\))\(\lfloor\frac{n}{i}\rfloor\) 表示在 \((i, \frac{n}{i})\) 下方的那条 \(y\) 值整数线(\(y=1\))。\(\cfrac{n}{\lfloor\frac{n}{i}\rfloor}\) 表示的就是其对应横坐标的值(\(x=7\)),将其取 \(floor\) 就是最靠右的整数解了。注意如果 \(\cfrac{n}{\lfloor\frac{n}{i}\rfloor}\) 就是整数,仍在这一块中。

考虑其复杂度。在 \([1,\sqrt{n}]\) 中最多存在 \(\sqrt{n}\) 个块,在 \([\sqrt{n},n]\) 中也最多存在 \(\sqrt{n}\) 个块。因此 \(O(\sqrt n)\)。
分块是根号算法。

#include <bits/stdc++.h>
using namespace std;
#define f(i, a, b) for (int i = (a); i <= (b); i++)
#define cl(i, n) i.clear(), i.resize(n);
#define endl '\n'
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int inf = 1e9;
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(NULL);
    cout.tie(NULL);
    int n;
    cin >> n;
    int ans = 0;
    for (int l = 1, r; l <= n; l = r + 1)
    {
        r = n / (n / l);
        ans += (r - l + 1) * (n / l);
    }
    cout << ans << endl;
    return 0;
}

标签:lfloor,frac,分块,int,rfloor,cfrac,sqrt,整除
来源: https://www.cnblogs.com/Zeardoe/p/16450529.html