整除分塊:
例題:
已知 \(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;
}