2017第四场多校联合 hdu6069

来源:互联网 发布:js获取标签name值 编辑:程序博客网 时间:2024/06/05 15:37

题目

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

题解:首先要知道的知识点是:对于一个知识点N,如果它可以被分解为pa11pa22.....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 longconst 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);    }}
原创粉丝点击