In mathematics, the function d(n)d(n) denotes the number of divisors of positive integer nn.
For example, d(12)=6d(12)=6 because 1,2,3,4,6,121,2,3,4,6,12 are all 1212's divisors.
In this problem, given l,rl,r and kk, your task is to calculate the following thing :
(∑i=lrd(ik))mod998244353(∑i=lrd(ik))mod998244353
Input
The first line of the input contains an integer T(1≤T≤15)T(1≤T≤15), denoting the number of test cases.
In each test case, there are 33 integers l,r,k(1≤l≤r≤1012,r−l≤106,1≤k≤107)l,r,k(1≤l≤r≤1012,r−l≤106,1≤k≤107).
Output
For each test case, print a single line containing an integer, denoting the answer.
Sample Input
3 1 5 1 1 10 2 1 100 3
Sample Output
10 48 2302
题意:给了一个公式 d(x) 求的是x的因子个数,现在求 x属于【l , r】的 d(x^k)的平方和。
思路:还是数学定理
x = p1 ^ m1 * p2 ^ m2 * ... * pn ^mn
那么因子个数为: (m1 + 1) * (m2 +1 ) * ... * ( mn + 1 )
再看这道题,是求x^k的因子个数,也就是 x^k = p1 ^ m1*k * p2 ^ m2*k * ... * pn ^mn*k
那么因子个数 : (m1*k + 1) * (m2*k +1 ) * ... * ( mn*k + 1 )
我就枚举 [ l , r ],结果TLE,QAQ...
然后就百度了一下,看了大佬的思路,因为区间的大小只有100w,所以我们就可以直接通过直接枚举素数在这个区间的倍数,然后记录次数。
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define LL long long
#define N 1000010
#define mod 998244353
using namespace std;
LL a[N],b[N];
int ces,p[N];
bool ver[N];
void init() //打素数表
{
ces=0;
memset(ver,false,sizeof(ver));
for(int i=2; i<N; i++)
if(!ver[i])
{
p[ces++]=i;
for(int j=2*i; j<N; j+=i)
ver[j]=true;
}
}
int main()
{
int t;
init();
scanf("%d",&t);
while(t--)
{
LL r,l,k;
scanf("%lld %lld %lld",&l,&r,&k);
for(LL i=l; i<=r; i++) //把这个区间的数记录下来
{
a[i-l]=1; //i是某个素数p[]的幂数
b[i-l]=i; //记录这个数
}
for(int i=0; i<ces&&p[i]*p[i]<=r; i++) //枚举在这个区间内所有素数的倍数
{
LL v=(LL)(l/p[i])*p[i]; //找到这个素数的倍数最接近l的数
//cout<<l<<" "<<p[i]<<" "<<v<<endl;
while(v<l) // v>=l 进入区间内
v+=p[i];
while(v<=r) //在区间内找所有倍数
{
int cns=0;
while(b[v-l]%p[i]==0) //幂次
{
cns++;
b[v-l]/=p[i];
}
a[v-l]=(a[v-l]*(k*cns+1))%mod; //记录幂次
v+=p[i];
}
}
LL ans=0;
for(LL i=l; i<=r; i++) //枚举区间内的标记情况
{
if(b[i-l]==1) //i是某个素数的x次幂
ans=(ans+a[i-l])%mod;
else
ans=(ans+(a[i-l]*(k+1)%mod))%mod;
}
printf("%lld\n",ans);
}
return 0;
}