整除分块
整除分块:
例题:
已知 \(f(n) =\sum\limits_{i = 1 }^{n}\left\lfloor\frac{n}{i}\right\rfloor\),给定 \(n\),求 \(f(n)\) 的值。
固然可以 \(O(n)\) 暴力,但显然会\(TLE\)。
计算一下前几项的值之后可以发现\(\left \lfloor \frac{n}{i} \right \rfloor\) 的取值在连续的一段区间内是相同的,那么就可以将其分为若干块分别进行计算。
先让 \(l\) 为区间的左端点,那么这块的值都为 \(k = \left\lfloor\frac{n}{l}\right\rfloor\) , \(r=max(i)=\left\lfloor\frac{n}{k}\right\rfloor\)。将 \(k\) 代入,得到 \(r=\left\lfloor\frac{n}{\left\lfloor\frac{n}{l}\right\rfloor}\right\rfloor\)。这样每一块的左右端点都能用确定的式子得到了。这样分块的值就为单值 $\times $ 区间长度,即 \(k\times (r-l+1)\) 。
模板:
代码
ll division_block(ll n){
ll res = 0;
for(ll l = 1, r; l <= n; l = r + 1){
r = n / (n / l);
res += n / l * (r - l + 1);
}
return res;
}