hdu 6069 Counting Divisors(约数个数)(2017 Multi-University Training Contest

来源:互联网 发布:文献法包括网络 编辑:程序博客网 时间:2024/05/22 16:40

Counting Divisors

题目链接:Counting Divisors

题意:d[i]表示i的约数有多少个,求这里写图片描述

官方题解:
这里写图片描述

我来解释一下,
任意一个数n都可以表示成n=p1c1p2c2....pkck,那么n的因子个数则为(c1+1)(c2+1)...(ck+1)
那么d(nm)=(c1m+1)(c2m+1)...(ckm+1)

因此我们只需要遍历[l,r]区间内所有数,对每一个数的求出它每一个质因子的个数即可

又r<=1e12,r最大为1e6,而对于r来说,大于r的质因子最多只有一个。因此我们可以只打出1e6的素数表,对于有大于r的质因子的情况我们只需要判断一下乘上(k+1)即可

代码:

#include<bits/stdc++.h>using namespace std;typedef long long LL;const LL maxn=1e6+10;const LL mod=998244353;LL prime[maxn/10],num[maxn],sum[maxn];//sum[i]记录i+le的约数个数bool vis[maxn];LL k,tot,ri,le;void Table()//1e6以内的素数打表{    tot=0;    for(LL i=2; i<maxn; ++i)    {        if(!vis[i])            prime[tot++]=i;        for(LL j=0; j<tot&&i*prime[j]<maxn; ++j)        {            vis[i*prime[j]]=true;            if(i%prime[j]==0)                break;        }    }}LL solve(){    for(LL i=0; i<tot&&prime[i]*prime[i]<=ri; ++i)    {        LL tmp=le;        if(tmp%prime[i])//将tmp变成>=le的第一个能整除prime[i]的数            tmp=(tmp/prime[i]+1)*prime[i];        for(LL j=tmp; j<=ri; j+=prime[i])//j都能整除prime[i]        {            LL cnt=0;            while(num[j-le]%prime[i]==0)            {                ++cnt;                num[j-le]/=prime[i];            }            sum[j-le]=(sum[j-le]*(cnt*k+1)%mod)%mod;        }    }    LL ans=0;    for(LL i=0; i<=ri-le; ++i)    {        if(num[i]>1)//对于有大于sqrt(r)的素因子的情况进行判断            ans=(ans+sum[i]*(k+1)%mod)%mod;        else            ans=(ans+sum[i])%mod;    }    return ans;}int main(){    Table();    int t;    scanf("%d",&t);    while(t--)    {        scanf("%lld%lld%lld",&le,&ri,&k);        for(LL i=0; i<=ri-le; ++i)            num[i]=i+le,sum[i]=1;        printf("%lld\n",solve());    }    return 0;}
阅读全文
1 0
原创粉丝点击