[hdu 6069]素数筛+区间质因数分解

给[L,R]区间的每一个数都质因数分解的复杂度可以达到(R-L)logR,真的涨姿势……

另外,质因数分解有很重要的一点,就是只需要打sqrt(R)以内的素数表就够了……因为超过sqrt(R)的至多只有一个,分解其他的那些剩下的就是了。

果然学习的过程中要精益求精,把时间和空间都尽量降到最低。

此外还有一个很重要的公式。d(i)表示i的因子个数。那么

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int MAXN=1000000;
int prime[MAXN+1];
void getPrime()
{
    memset(prime,0,sizeof(prime));
    for(int i=2; i<=MAXN; i++)
    {
        if(!prime[i])prime[++prime[0]]=i;
        for(int j=1; j<=prime[0]&&prime[j]<=MAXN/i; j++)
        {
            prime[prime[j]*i]=1;
            if(i%prime[j]==0) break;
        }
    }
}

const int md=998244353;
long long sj[MAXN+2];
long long fj[MAXN+2];
long long k;

void getfact(long long l,long long r)
{
    for (long long i=l;i<=r;i++)
    {
        fj[i-l]=1;
        sj[i-l]=i;
    }
    for (int i=1;i<=prime[0];i++)
    {
        long long th=prime[i];
        for (long long j=(l-1)/th*th+th;j<=r;j+=th)
        {
            int cnt=0;
            while (sj[j-l]%th==0)
            {
                cnt++;
                sj[j-l]/=th;
            }
            fj[j-l]=fj[j-l]*(k*cnt%md+1)%md;
        }
    }
    for (long long i=l;i<=r;i++)
    {
        if (sj[i-l]!=1)
        {
            fj[i-l]=fj[i-l]*(k+1)%md;
        }
    }
}

int main()
{
    getPrime();
    int t;
    scanf("%d",&t);
    while (t--)
    {
        ll l,r;
        scanf("%I64d%I64d%I64d",&l,&r,&k);
        getfact(l,r);
        long long ans=0;
        for (long long i=l;i<=r;i++)
        {
            ans=(ans+fj[i-l])%md;
        }
        printf("%I64d\n",ans);
    }
    return 0;
}

 

posted @ 2017-08-03 22:02  ACMsong  阅读(495)  评论(0编辑  收藏  举报