整数分块学习笔记
——by sunzz3183
引入
求
∑i=1n⌊ni⌋ \sum\limits_{i=1}^{n}\left \lfloor \frac{n}{i} \right \rfloor i=1∑n⌊in⌋
正常求法:
直接枚举每个 nnn,时间复杂度为 O(n)O(n)O(n)。
可是,如果 1≤n≤1081\leq n \leq 10^81≤n≤108 呢?
所以,我们要用到分块的思想:整数分块
整数分块
显然
∃1≤l≤r≤n,⌊ni⌋=⌊nj⌋(l≤i,j≤r) \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) ∃1≤l≤r≤n,⌊in⌋=⌊jn⌋(l≤i,j≤r)
我们会浪费很多的时间。
那么,有多少段相等呢?
我们来看一张图

显然,存在一个 kkk 使得
⌊nl⌋=k \left \lfloor \frac{n}{l} \right \rfloor =k ⌊ln⌋=k
并让
r=⌊nk⌋ r=\left \lfloor \frac {n}{k }\right \rfloor r=⌊kn⌋
让
⌊ni⌋=⌊nj⌋(l≤i,j≤r) \left \lfloor \frac{n}{i}\right \rfloor =\left \lfloor \frac{n}{j}\right \rfloor (l\leq i,j\leq r) ⌊in⌋=⌊jn⌋(l≤i,j≤r)
而显然 kkk 是由 lll 得到,rrr 是由 kkk 得到。
所以,我们去枚举 lll,并让 k,rk,rk,r 等于上面的东西。
而下一段区间的 lll 为 r+1r+1r+1。
每一段的值为
⌊nl⌋(r−l+1) \left \lfloor \frac{n}{l} \right \rfloor (r-l+1) ⌊ln⌋(r−l+1)
时间复杂度 O(n)O(\sqrt{n})O(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;
}
330



被折叠的 条评论
为什么被折叠?



