整数分块学习笔记
整数分块学习笔记
——by sunzz3183
引入
求
\[\sum\limits_{i=1}^{n}\left \lfloor \frac{n}{i} \right \rfloor
\]
正常求法:
直接枚举每个 \(n\),时间复杂度为 \(O(n)\)。
可是,如果 \(1\leq n \leq 10^8\) 呢?
所以,我们要用到分块的思想:整数分块
整数分块
显然
\[\exists 1\leq l\leq r \leq n,\left \lfloor \frac{n}{i}\right \rfloor =\left \lfloor \frac{n}{j}\right \rfloor (l\leq i,j\leq r)
\]
我们会浪费很多的时间。
那么,有多少段相等呢?
我们来看一张图
显然,存在一个 \(k\) 使得
\[\left \lfloor \frac{n}{l} \right \rfloor =k
\]
并让
\[r=\left \lfloor \frac {n}{k }\right \rfloor
\]
让
\[\left \lfloor \frac{n}{i}\right \rfloor =\left \lfloor \frac{n}{j}\right \rfloor (l\leq i,j\leq r)
\]
而显然 \(k\) 是由 \(l\) 得到,\(r\) 是由 \(k\) 得到。
所以,我们去枚举 \(l\),并让 \(k,r\) 等于上面的东西。
而下一段区间的 \(l\) 为 \(r+1\)。
每一段的值为
\[\left \lfloor \frac{n}{l} \right \rfloor (r-l+1)
\]
时间复杂度 \(O(\sqrt{n})\)。
代码
int division_block(int n){
int sum=0;
for(int l=1,r;l<=n;l=r+1)
r=n/(n/l),sum+=n/l*(r-l+1);
return sum;
}