官方题解:
设n=p1c1p2c2...pmcm,则d(nk)=(kc1+1)(kc2+1)...(kcm+1)。
枚举不超过√r的所有质数p,再枚举区间[l,r]中所有p的倍数,将其分解质因数,最后剩下的部分就是超过√r的质数,只可能是0个或1个。
重点是直接循环复杂度撑不住,我们思考,对于第二重循环是不是存在很多无用功呢?当不是当前素数的倍数的时候,是没必要枚举的。所以优化掉/*
*注意,枚举质因子的时候,直接去枚举区间内当前质因子的倍数。
*不难发现其余的纯粹是浪费时间
*/
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e6+7;
typedef long long LL;
const long long mod = 998244353;
int n;
bool vis[MAXN];
LL prim[MAXN], p[MAXN];
LL ans[MAXN];
int prim_cnt;
void get_prim()
{
prim_cnt = 0;
for(int i = 2; i <= 1000; ++i)
{
if(!vis[i])
{
for(int j = i*i; j <= 1000000; j+=i)vis[j] = 1;
}
}
for(int i = 2; i <= 1000000; ++i)if(!vis[i])prim[prim_cnt++] = i;
}
int main()
{
int t;
get_prim();
scanf("%d",&t);
LL l,r,k;
while(t--)
{
scanf("%I64d%I64d%I64d",&l,&r,&k);
for(int i = 0; i <= r-l; ++i)
{
p[i] = l+i;
ans[i] = 1;
}
for(int i = 0; i < prim_cnt; ++i)
{
if(prim[i]*prim[i] > r)break;
LL tt = l%prim[i];
for(int j = (prim[i]-tt)%prim[i]; j <= r-l; j += prim[i])
{
LL sum = 0;
while(p[j]%prim[i]==0)
{
sum++;
p[j]/=prim[i];
}
sum = sum*k+1;
ans[j]*=sum;
ans[j]%=mod;
}
}
LL Ans = 0;
for(int i = 0; i <= r-l; ++i)
{
if(p[i] != 1)ans[i]=ans[i]*(k+1)%mod;
Ans += ans[i];
if(Ans >= mod)Ans -= mod;
}
printf("%I64d\n",Ans);
}
return 0;
}