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

原题:HDU - 6069

题意:令d(x)表示x的因子数,求 i = l r d ( i k ) ,r,l 为1e12 ,r-l为1e6

解析:

刚开始想到的是欧拉函数值,结果 i k 就劝退了,换一种常规的思路,从因子的角度去思考,按照基本定理:

n = p 1 q 1 p 2 q 2 . . . p n q n d ( n ) = ( q 1 + 1 ) ( q 2 + 1 ) . . . ( q n + 1 )
那么我们可以枚举素数,然后对这个区间内的数进行除法运算,就可以得出答案了,而k次幂只是 ( q n + 1 ) 变成 ( k q n + 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);

    }
}

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/82695283
今日推荐