1. 程式人生 > >Counting Divisors((l~r)^k的因子數和)

Counting Divisors((l~r)^k的因子數和)

題意:令d(x)表示x的因子數,求i=lrd(ik),r,l 為1e12 ,r-l為1e6

解析:

剛開始想到的是尤拉函式值,結果ik就勸退了,換一種常規的思路,從因子的角度去思考,按照基本定理:

n=p1q1p2q2...pnqnd(n)=(q1+1)(q2+1)...(qn+1)那麼我們可以列舉素數,然後對這個區間內的數進行除法運算,就可以得出答案了,而k次冪只是(qn+1)變成(kqn+1)而已

程式碼:

#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); } }