您的位置:首页 > 其它

2017第四场多校联合 hdu6069

2017-08-04 20:11 113 查看
题目

题意:给你l,r,k,要求(∑i=lrd(ik))mod998244353。

题解:首先要知道的知识点是:对于一个知识点N,如果它可以被分解为pa11∗pa22.....pann,那么d(N)(即它的因子个数)=(a1+1)∗(a2+1)∗....∗(an+1)

知道了这个公式之后,那么我们只需要将给定数分解就好了,这里可以先将1-1e+10的素数全部筛选出来,选择小于r√的素数p,然后去和区间l-r的数进行处理,使l-r中所有p的因子提出来,然后分别记录p的指数就好了,(这里因子并不重要,重要的是因子的指数),最后会有无法处理的因子,这些因子的指数一定是1,单独处理就好了。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1000010,mod=998244353;
int p[maxn/10],g[maxn],ans,tot;
ll f[maxn],n,l,r,k;
bool vis[maxn];
void slove(ll p)
{
for(ll i=l/p*p; i<=r; i+=p)
{
if(i>=l)
{
int o=0;
while(f[i-l]%p==0)
{
f[i-l]/=p;
o++;
}
g[i-l]=1ll*g[i-l]*(o*k+1)%mod;
}
}
}
int main()
{
tot=0;
for(int i=2; i<maxn; i++)
{
if(!vis[i])
p[tot++]=i;
for(int j=0; j<tot&&i*p[j]<maxn; j++)
{
vis[i*p[j]]=1;
if(i%p[j]==0)
break;
}
}
int t;
scanf("%d",&t);
while(t--)
{
scanf("%lld %lld %lld",&l,&r,&k);
n=r-l;
for(int i=0; i<=n; i++)
f[i]=i+l,g[i]=1;
for(int i=0; i<tot; i++)
{
if(1ll*p[i]*p[i]>r)
break;
slove(p[i]);
}
ans=0;
for(int i=0; i<=n; i++)
{
if(f[i]>1)
{
g[i]=1ll*g[i]*(k+1)%mod;
}
ans=(ans+g[i])%mod;
}
printf("%d\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: