整除分块
跟数列的分块思路相似,但是绝对不一样!!!
〇、题目
给出\(N\),求\(\sum\limits^{N}_{i=1}\lfloor \dfrac{N}{i}\rfloor\)
一、思路
就比如说\(N=20\)的时候,我们发现,这些商下取整后的结果为:
i: | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
N/i | 20 | 10 | 6 | 5 | 4 | 3 | 2 | 2 | 2 | 2 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
观察前面还没什么特点,但是到后面就很明显:11到20一整段都是1。于是,我们想把商为一个数的这些除数分成一个块。
我们对于每一个\(i\in {1,2,3,...,n}\)首先找到当前的商\(T\),然后用\(R= \lfloor\dfrac{N}{T}\rfloor\)找到商相等的最后一个数,那我们的答案就加上\((R-i+1)\times T\),然后\(i\)就要跳到\(R+1\)。
二、代码
#include<bits/stdc++.h>
using namespace std;
long long n;
long long c(){
long long ans=0,l=1,r;//l就是i,r是R,ans是最终答案
for(;l<=n;l=r+1){//l已经初始化了,从1到n看,每次最后l=r+1
long long t=n/l;//t是T
r=n/t;//算出r
ans+=(r-l+1)*t;//加上这个区间的和
}
return ans;//返回
}
int main(){//输入输出
cin>>n;
cout<<c()<<endl;
return 0;
}
最后,求点赞,感谢你的阅读!