LOJ#6053. 简单的函数(min_25筛)

https://loj.ac/problem/6053

 

f(p^c)=p异或c

当p!=2时,f(p)=p-1

满足f在质数处是关于p的多项式,在质数的幂处可以快速求

所以可以用min_25筛

 

要预处理的是质数前缀和 以及 质数前缀个数和

 

这个数据范围一不小心就爆long long了。。。

 

#include<cmath>
#include<cstdio>

using namespace std;

const int mod=1e9+7;
typedef long long LL;

#define N 200001

LL n;
int sq;

int pr[N],tot;
bool vis[N];

LL w[N];
int m,id1[N],id2[N];

LL sump[N],g[N],h[N];

int MOD(LL x)
{
    return x%mod;
}

void pre()
{
    sq=sqrt(n);
    for(int i=2;i<=sq;++i)
    {
        if(!vis[i])
        {
            pr[++tot]=i;
            sump[tot]=(sump[tot-1]+i)%mod;
        }
        for(int j=1;j<=tot && 1ll*pr[j]*i<=sq;++j)
        {
            vis[pr[j]*i]=true;
            if(!(i%pr[j])) break;
        }
    }
    LL j,x;
    for(LL i=1;i<=n;i=j+1)
    {
        j=n/(n/i);
        x=n/i;
        w[++m]=x;
        if(x<=sq) id1[x]=m;
        else id2[n/x]=m;
        g[m]=(1ll*MOD(x)*MOD(x+1)/2%mod-1+mod)%mod;
        h[m]=(x-1)%mod;
    }
}

void solve1()
{
    int k;
    for(int j=1;j<=tot;++j)
        for(int i=1;i<=m && 1ll*pr[j]*pr[j]<=w[i];++i)
        {
            k=w[i]/pr[j]<=sq ? id1[w[i]/pr[j]] : id2[n/(w[i]/pr[j])];
            g[i]=(g[i]-1ll*pr[j]*(g[k]-sump[j-1])%mod+mod)%mod;
            h[i]=(h[i]-(h[k]-(j-1))+mod)%mod;
        }
}

LL solve2(LL x,int j)
{ 
    if(x<=pr[j]) return 0;
    int kk= x<=sq ? id1[x]: id2[n/x];
    LL gg=(g[kk]-sump[j]-(h[kk]-j)+mod)%mod;
    if(!j) gg+=2;
    LL now,sum=0;
    for(int k=j+1;k<=tot && 1ll*pr[k]*pr[k]<=x;++k)
    {
        now=pr[k];
        for(int e=1;now*pr[k]<=x;now*=pr[k],++e)
        {
            sum+=(pr[k]^e)%mod*solve2(x/now,k)%mod;
            sum+=(pr[k]^(e+1))%mod;
            sum%=mod;
        }
    }
    return (gg+sum)%mod;
}

int main()
{
    scanf("%lld",&n);
    if(n==1) 
    {
        printf("1");
        return 0;
    }
    pre();
    solve1();
    printf("%lld",(solve2(n,0)+1)%mod);
}

 

 

posted @ 2020-09-25 21:07  TRTTG  阅读(172)  评论(0编辑  收藏  举报