您的位置:首页 > 大数据 > 人工智能

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

2017-08-04 09:38 513 查看

Counting Divisors

题目链接:Counting Divisors

题意:d[i]表示i的约数有多少个,求


官方题解:



我来解释一下,

任意一个数n都可以表示成n=p1c1∗p2c2∗....∗pkck,那么n的因子个数则为(c1+1)∗(c2+1)∗...∗(ck+1)

那么d(nm)=(c1∗m+1)∗(c2∗m+1)∗...∗(ck∗m+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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐