容易发现,(f(x))等于因子数量。
对于(l,r)都很大的题目,一般可以采用前缀和的方式解决。
设(sum(x)=sum_{i=1}^{i<=x} f(i))
考虑枚举因数。
如果一个因数为(v),那么在(1->x)的范围内,(v)出现了(lfloor x/v floor)次.
于是我们可以这样子表示(sum(x)):
[ sum(x)=sum_{i=1}^{i<=x} lfloor x/i
floor
]
观察一下规律:
比如我们要求(sum(14)),那么求解过程如下:
[ 14/1=14\
14/2=7\
14/3=4\
14/4=3\
14/5=2\
14/6=2\
14/7=2\
14/8=1\
14/9=1\
14/10=1\
14/11=1\
14/12=1\
14/13=1\
14/14=1\
]
发现有很多重复的,比如:
[14/5=2\
14/6=2\
14/7=2\
]
于是我们可以把它划分成若干个重复的序列进行求解
我们把重复的左边设作(l),(这里的(l=5))
我们把重复的右边设作(r),(这里的(r=7))
发现一个性质:
[ lfloor v/l
floor=lfloor v/r
floor
]
如果我们知道了(l),那么L
[ r=v/lfloor v/l
floor\
]
上面的式子可以举例子感性理解得出
当然,你也可以二分求解这个(r)((O(log_2(n)))
我们知道了(l,r)之后,那么对(sum(x))的贡献就是(lfloor x/l floor imes(r-l+1))。
关于时间复杂度:
如果你知道,请告诉我
不过根据跑出来的时间我猜是(sqrt{n})级别的
类似题目:余数求和
记得:取模取模取模取模取模取模
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<map>
#include<queue>
#include<iostream>
#include<cmath>
#define int long long
using namespace std;
inline int gi(){char tmp=getchar();int flag=1;while(tmp<'0'||tmp>'9'){if(tmp=='-'){flag=-1;tmp=getchar();break;}tmp=getchar();}int ans=0;while(tmp<='9' and tmp>='0') {ans=ans*10+tmp-'0';tmp=getchar();}return ans*flag;}
inline void write(int x){static int stk[100], top = 0;if (x == 0) { putchar('0'); putchar(' ');return; }if (x < 0) { x = -x; putchar('-'); }while (x) { stk[++top] = x % 10; x /= 10; }while (top) { putchar(stk[top--] + '0'); }putchar(' ');}
#define line() putchar('
');
#define Mem(Arr,V) memset(Arr,V,sizeof Arr);
#define Mcpy(Arr,qwq) memcpy(Arr,qwq,sizeof qwq);
#define max3(a,b,c) max(max(a,b),c)
#define max4(a,b,c,d) max4(max3(a,b,c),d);
#define in(a) a=gi()
#define in2(a,b) in(a),in(b)
#define in3(a,b,c) in2(a,b),in(c)
#define in4(a,b,c,d) in3(a,b,c),in(d)
#define write2(a,b) write(a),write(b)
#define write3(a,b,c) write2(a,b),write(c)
#define write4(a,b,c,d) write3(a,b,c),write(d)
const int mod=998244353;
inline void smin(int &x,int y){x=min(x,y);}
inline void smax(int &x,int y){x=max(x,y);}
inline int Mul(int x,int y)
{
int ans=0;
while(y)
{
if(y&1) ans+=x;
x=x+x;
x%=mod;
ans%=mod;
y>>=1;
}
if(ans<=0)
{
write2(x,y);
exit(0);
}
return ans;
}
inline int Sum(int v)
{
if(v==0) return 0;
int ans=0;
for(int l=1,r;l<=v;l=r+1)
{
r=v/(v/l);
ans+=((r-l+1)%mod*((v/l)%mod));
ans%=mod;
if(ans<=0)
{
// write2(x,y);
exit(0);
}
l=r+1;
}
return ans%mod;
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("data.in","r",stdin);
#endif
int l,r;
in2(l,r);
// write(Mul(l,r));
// return 0;
write(((Sum(r)-Sum(l-1)%mod)+mod)%mod);
return 0;
}