题目
约数统计
分析
- 对于前六个测试点,可以很快地用线性筛筛出质数,再对每个点用约数个数定理算一下,对于 k ,其实每次*cnt 的时候把cnt乘一下 k 即可。
- 然后后面四个大数据点,这样就不行了,你筛不出这么多质数,直接暴力一个个数判也不行。
- 想一想发现,
r-l<=10^6
,且 r^2 之后的质数在范围内的数只能出现一次幂或0次。 - 于是可以筛出
sqrt(r)
之内的质数,把l~r
的所有数暴力除,弄完sqrt(r)
以内的数之后,若l~r
中的数还有不为 1 的,那它们肯定是大于sqrt(r)
的某个质数的几倍,直接对它的 d 值再乘k+1
即可。
程序
#include <cstdio>
#define Ha 998244353
typedef long long ll;
ll l,r,k,N,d[1000005];
ll p[1000005],rest[1000005],num,ans;
bool f[1000005];
int main(){
scanf("%lld%lld%lld",&l,&r,&k); l--;
N=r-l;
for (ll i=l+1; i<=r; i++) d[i-l]=1,rest[i-l]=i;
for (ll x=2; x*x<=r; x++){
if (!f[x]){
p[++num]=x;
ll ytx=l/x*x+x,cnt;
for (cnt=0; ytx<=r; ytx+=x,cnt=0){
while (rest[ytx-l]%x==0)
rest[ytx-l]/=x,cnt++;
cnt=(cnt*k+1)%Ha;
d[ytx-l]=d[ytx-l]*cnt%Ha;
}
}
for (ll i=1; i<=num && x*p[i]<=1000000; i++) f[x*p[i]]=1;
}
for (ll i=l+1; i<=r; i++) if (rest[i-l]>1) d[i-l]=d[i-l]*(k+1)%Ha;
for (ll i=l+1; i<=r; i++) ans=(ans+d[i-l])%Ha;
printf("%lld",ans);
}