Counting Divisors((l~r)^k的因子數和)
阿新 • • 發佈:2018-12-09
題意:令d(x)表示x的因子數,求,r,l 為1e12 ,r-l為1e6
解析:
剛開始想到的是尤拉函式值,結果就勸退了,換一種常規的思路,從因子的角度去思考,按照基本定理:
那麼我們可以列舉素數,然後對這個區間內的數進行除法運算,就可以得出答案了,而k次冪只是變成而已程式碼:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define ll long long
LL read(){ LL ans=0; char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
const LL mod=998244353ll;
const int N=1000000;
LL pri[N+9],now;
bool vis[N+9];
void init(){
now=0;vis[1]=1;
for(int i=2;i<=N;i++){
if(!vis[i])pri[++now]=i;
for(int j=1;j<=now&&pri[j]*i<=N;j++){
vis[pri[j]*i]=1;
if(i%pri[j]==0)break;
}
}
}
LL ans[N+9],Num[N+9];
LL l,r,k;
int id(LL x){return x-l+1; }//l~r拉到1~r-l+1以開陣列
LL val(int x){return x+l-1;}
int main(){
init();
int t=read();
while(t--){
l=read(),r=read(),k=read();
for(int i=1,idx=id(r);i<=idx;i++)ans[i]=1,Num[i]=val(i);
for(int i=1;i<=now;i++){//列舉素數
LL J=pri[i];
LL st=(l/J*J==l)?l:(l/J*J+J);//第一個區間內此素數的倍數
for(int idx=id(st),en=id(r) ; idx<=en ; idx+=J){//列舉區間內的數
int ct=0;
while(Num[idx]%J==0)Num[idx]/=J,ct++;
ans[idx]=ans[idx]*((k*ct+1)%mod)%mod;
}
}
LL A=0;
for(int i=1,en=id(r);i<=en;i++)
if(Num[i]>1)A=(A+((k+1)*ans[i]%mod))%mod;
else A=(A+ans[i])%mod;
printf("%lld\n",A);
}
}