hdu6069 区间素数筛
hdu6069 Counting Divisors
传送门
题意
计算\((\sum_{i=l}^{r}d(i^k))\ mod\ 998244353\),其中\(d(n)\)表示\(n\)的约数个数,其中\(1\leq l\leq r\leq 1e12,r-l\leq 1e6,1\leq k\leq 1e7\)
题解
根据唯一分解定理
\(n=p_1^{c_1}*p_2^{c_2}*p_3^{c_3}*...*p_m^{c_m}\)
所以
\(d(n)=(c_1+1)*(c_2+1)*(c_3+1)*...*(c_m+1)\)
所以
\(d(n^k)=(kc_1+1)*(kc_2+1)*(kc_3+1)*...*(kc_m+1)\)
所以就是对\([l,r]\)区间中的每一个数进行质因数分解,可以通过区间素数筛计算每一个素数的贡献
#include<iostream>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<cstring>
#include<string>
#include<sstream>
#include<cmath>
#include<ctime>
#include<climits>
#include<algorithm>
#define LL long long
#define PII pair<int,int>
#define PLL pair<LL,LL>
#define PLI pair<LL,int>
#define pi acos(-1.0)
#define eps 1e-6
#define lowbit(x) x&(-x)
using namespace std;
const int maxn=1e6+10,mod=998244353;
int T;
bool is_prime[maxn];
LL l,r,k,ans[maxn],cur[maxn];
void segment_sieve(LL a,LL b){
int t=sqrt(b);
for(int i=2;i<=t;i++) is_prime[i]=1;
for(int i=0;i<=b-a;i++) cur[i]=i+a;
for(int i=2;i<=t;i++){
if(is_prime[i]){
for(int j=2*i;j<=t;j+=i){
is_prime[j]=0;
}
for(LL j=(a+i-1)/i*i;j<=b;j+=i){
LL cnt=0;
while(cur[j-a]%i==0){
cnt++;
cur[j-a]/=i;
}
cnt=cnt*k%mod;
ans[j-a]=ans[j-a]*(cnt+1)%mod;
}
}
}
for(int i=0;i<=b-a;i++){
if(cur[i]!=1){
ans[i]=ans[i]*(k+1)%mod;
}
}
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%lld %lld %lld",&l,&r,&k);
LL n=r-l+1;
for(int i=0;i<n;i++) ans[i]=1;
segment_sieve(l,r);
LL res=0;
for(int i=0;i<n;i++){
res=(res+ans[i])%mod;
}
printf("%lld\n",res);
}
}