LOJ#6053. 简单的函数

Description

某一天,你发现了一个神奇的函数$f(x)$,它满足很多神奇的性质:

$f(1)=1$。
$f(p^c)=p⊕c$($p$ 为质数,$⊕$ 表示异或)。
$f(ab)=f(a)f(b)$($a$ 与 $b$ 互质)。
你看到这个函数之后十分高兴,于是就想要求出 $\sum_{i=1}^n f(i)$。

由于这个数比较大,你只需要输出 $\sum_{i=1}^n f(i) \bmod(10^9+7)$。

Solution

发现对于除了$2$的所有质数,$p⊕1=p-1$,所以可以视为函数在质数处的取值等于$p-1$,最终答案+2

所以$g(x)=x-1$,做Min_25筛,特判$n=1$的情况

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int tot,cnt,id1[100005],id2[100005];
const int mod=1e9+7;
long long w[200005],g1[200005],g0[200005],sp[100005],sq,prime[100005];
bool vst[100005];
long long n;
inline long long read(){
    long long f=1,w=0;
    char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=getchar();
    return f*w;
}
long long S(long long x,int y){
    if(prime[y]>=x)return 0;
    int id=x<=sq?id1[x]:id2[n/x];
    long long ret=(g1[id]-g0[id]+mod-(sp[y]-y+mod)+mod)%mod;
    for(int i=y+1;i<=tot&&prime[i]*prime[i]<=x;i++){
        long long temp=prime[i];
        for(int e=1;temp<=x;e++,temp*=prime[i])(ret+=(prime[i]^e)*(S(x/temp,i)+(e!=1))%mod)%=mod;
    }
    return ret;
}
int main(){
    n=read(),sq=sqrt(n);
    if(n==1)return puts("1"),0;
    for(int i=2;i<=sq;i++){
        if(!vst[i])prime[++tot]=i,sp[tot]=(sp[tot-1]+i)%mod;
        for(int j=1;j<=tot&&i*prime[j]<=sq;j++){
            vst[i*prime[j]]=true;
            if(!(i%prime[j]))break;
        }
    }
    for(long long i=1;i<=n;){
        long long j=n/(n/i);
        w[++cnt]=n/i%mod,g1[cnt]=((w[cnt]+1)*w[cnt]/2%mod+mod-1)%mod,g0[cnt]=(w[cnt]+mod-1)%mod,w[cnt]=n/i,n/i<=sq?id1[n/i]=cnt:id2[n/(n/i)]=cnt,i=j+1;
    }
    for(int i=1;i<=tot;i++)for(int j=1;j<=cnt&&prime[i]*prime[i]<=w[j];j++){
        int id=w[j]/prime[i]<=sq?id1[w[j]/prime[i]]:id2[n/(w[j]/prime[i])];
        (g1[j]+=mod-prime[i]*(g1[id]-sp[i-1])%mod)%=mod,(g0[j]+=mod-(g0[id]-i+1))%=mod;
    }
    printf("%lld\n",S(n,0)+3);
    return 0;
}
简单的函数

 

posted @ 2021-02-28 21:17  QDK_Storm  阅读(81)  评论(0编辑  收藏  举报