题目描述
分析
设 i=pr11pr22…prkk ,则 d(i)=∏ki=1(ri+1) ,因此我们有 d(ik)=∏ki=1(ri∗k+1) ,显然用区间筛法,可以做到在 O(r√log(r−l+1)) 内解决.具体来说用一个数组num保存每一个数的d,用f对 l−r 里的数离散化并保存每个数除了后的值.
AC code
//Problem : 6069 ( Counting Divisors ) Judge Status : Accepted
//RunId : 21499348 Language : G++ Author : zouzhitao
//Code Render Status : Rendered By HDOJ G++ Code Render Version 0.01 Beta
#include<bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define PI acos(-1)
#define fi first
#define se second
#define INF 0x3f3f3f3f
#define INF64 0x3f3f3f3f3f3f3f3f
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define ms(x,v) memset((x),(v),sizeof(x))
using namespace std;
const int MOD = 998244353;
const double eps = 1e-8;
typedef long long LL;
typedef long double DB;
typedef pair<int,int> Pair;
const int maxn = 1e6+10+10;
const int maxv = 1e5;
LL l,r,k;
LL prime[maxn],cnt;
void init(){
memset(prime,0,sizeof(prime));
cnt =0;
for(int i=2 ;i<maxn ; ++i){
if(!prime[i]){
prime[cnt++] = i;
}
for(int j=0 ; j<cnt && i*prime[j]<maxn ; ++j){
prime[i*prime[j]] = 1;
if(i % prime[j] == 0)break;
}
}
}
LL f[maxn],num[maxn];
int main()
{
init();
//cout<<cnt<<endl;
int T;
scanf("%d",&T);
while(T--){
scanf("%lld%lld%lld",&l,&r,&k);
int t= r-l;
for(int i=0 ; i<=t ; ++i)f[i] = i+l,num[i] =1;
for(int i=0 ; i<cnt && prime[i]*prime[i] <=r ; ++i){
for(LL j = ((l-1)/prime[i]+1)*prime[i] ; j <=r ; j+=prime[i]){
int cnt =0;
while (f[j-l] % prime[i] ==0) {
f[j-l] /= prime[i];cnt++;
}
num[j-l] = num[j-l]*(cnt*k+1) % MOD;
}
}
LL ans = 0;
for(int i=0 ; i<=t ; ++i){
if(f[i] ==1){
ans = (ans+num[i]) % MOD;
}else ans = (ans+num[i]*(k+1)) % MOD;
}
std::cout << ans << '\n';
}
return 0;
}