P3935 Calculating
题目大意
求:
∑ i = l r d ( i ) \large\sum\limits_{i=l}^rd(i) i=l∑rd(i)
其中 d ( i ) d(i) d(i) 表示 i i i 的约数个数
题解
首先进行一下容斥:
∑ i = 1 r d ( i ) − ∑ i = 1 l − 1 d ( i ) \large\sum\limits_{i=1}^rd(i)-\sum\limits_{i=1}^{l-1}d(i) i=1∑rd(i)−i=1∑l−1d(i)
接下来我们只考虑 ∑ i = 1 n d ( i ) \sum\limits_{i=1}^nd(i) i=1∑nd(i) 怎么求。转化 d ( i ) = ∑ d ∣ i 1 d(i)=\sum\limits_{d\mid i}1 d(i)=d∣i∑1:
∑ i = 1 n ∑ d ∣ i 1 \large\sum\limits_{i=1}^n\sum\limits_{d\mid i}1 i=1∑nd∣i∑1
令 i = i ′ d i=i^\prime d i=i′d,可以得到:
∑ d = 1 n ∑ i = 1 ⌊ n d ⌋ 1 \large\sum\limits_{d=1}^n\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}1 d=1∑ni=1∑⌊dn⌋1
发现这玩意跟 i i i 一点关系都没有,直接删掉:
∑ i = 1 n ⌊ n i ⌋ \large\sum\limits_{i=1}^n\left\lfloor\dfrac{n}{i}\right\rfloor i=1∑n⌊in⌋
就做完了,整除分块时间复杂度 O ( n ) \mathcal{O}(\sqrt{n}) O(n)。
代码
//P3935
#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int read(){
char op=getchar();
int w=0,s=1;
while(op<'0'||op>'9'){
if(op=='-') s=-1;
op=getchar();
}
while(op>='0'&&op<='9'){
w=(w<<1)+(w<<3)+op-'0';
op=getchar();
}
return w*s;
}
int l,r;
const int mod=998244353;
int Mul(int a,int b){return (a%mod*b%mod)%mod;}
int Add(int a,int b){return (a+b)%mod;}
int Dec(int a,int b){return (a-b+mod)%mod;}
int Sqrt(int x){
int ans=0,j=0;
for(register int i=1;i<=x;i=j+1){
j=x/(x/i);
ans=Add(ans,Mul(j-i+1,x/i));
}
return ans;
}
signed main(){
l=read(),r=read();
printf("%lld\n",(Sqrt(r)-Sqrt(l-1)+mod)%mod);
}