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) mod(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 ",S(n,0)+3); return 0; }