【整除分块】Calculating

原题链接

P3935 Calculating

题目大意

求:

∑ i = l r d ( i ) \large\sum\limits_{i=l}^rd(i) i=lrd(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=1rd(i)i=1l1d(i)

接下来我们只考虑 ∑ i = 1 n d ( i ) \sum\limits_{i=1}^nd(i) i=1nd(i) 怎么求。转化 d ( i ) = ∑ d ∣ i 1 d(i)=\sum\limits_{d\mid i}1 d(i)=di1

∑ i = 1 n ∑ d ∣ i 1 \large\sum\limits_{i=1}^n\sum\limits_{d\mid i}1 i=1ndi1

i = i ′ d i=i^\prime d i=id,可以得到:

∑ 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=1ni=1dn1

发现这玩意跟 i i i 一点关系都没有,直接删掉:

∑ i = 1 n ⌊ n i ⌋ \large\sum\limits_{i=1}^n\left\lfloor\dfrac{n}{i}\right\rfloor i=1nin

就做完了,整除分块时间复杂度 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);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值