[LOJ6053]简单的函数
题目
题解
注意到 \(f(p)=p-1,(p\neq 2\; and\; p\in \Bbb P)\).
对于其他情况来说,\(f_0(x)=1,a_0=-1\),对于 \(2\) 来说,\(f_0(x)=1,a_0=1\),并且有 \(f_1(x)=x\).
我们可以先将 \(2\) 的 \(a_0\) 当成 \(-1\) 来做,这样答案会被少算 \(2\),最后加上即可,然后用一般思路即可.
最后注意特判 \(n=1\) 的情况.
代码
const int maxn=1e5*2;
const int mod=1e9+7;
const int inv2=500000004;
ll n;int sqn;
int sie[maxn+5];
int prime[maxn>>2],pcnt;
int ppre[maxn>>2];
inline void sieve(const int up){
sie[1]=1;
rep(i,2,up){
if(!sie[i])prime[++pcnt]=i;
for(int j=1;j<=pcnt && i*prime[j]<=up;++j){
sie[i*prime[j]]=1;
if(i%prime[j]==0)break;
}
}
rep(i,1,pcnt)ppre[i]=(ppre[i-1]+prime[i])%mod;
}
ll w[maxn+5];
int id[2][maxn+5],wcnt;
inline int getid(const ll x){
if(x<=sqn)return id[0][x];
return id[1][n/x];
}
inline void hash_w(){
for(ll l=1,r;l<=n;l=r+1){
r=n/(n/l);
w[++wcnt]=n/l;
if(w[wcnt]<=sqn)id[0][w[wcnt]]=wcnt;
else id[1][n/w[wcnt]]=wcnt;
}
}
int g0[maxn+5],g1[maxn+5];
inline void getg(){
rep(i,1,wcnt){
// 去掉 f(1)
g0[i]=(w[i]%mod+mod-1)%mod;
// 去掉 f(1)
g1[i]=(1ll*w[i]%mod*(w[i]%mod+1)%mod*inv2%mod+mod-1)%mod;
}
rep(j,1,pcnt){
for(int i=1;i<=wcnt && 1ll*prime[j]*prime[j]<=w[i];++i){
g0[i]=(g0[i]+mod-(g0[getid(w[i]/prime[j])]+mod-(j-1))%mod)%mod;
g1[i]=(g1[i]+mod-1ll*prime[j]*(g1[getid(w[i]/prime[j])]+mod-ppre[j-1])%mod)%mod;
}
}
}
int S(const ll x,const int j){
if(prime[j]>=x)return 0;
int ret=(g1[getid(x)]+mod-g0[getid(x)])%mod;
ret=(ret+mod-(ppre[j]+mod-j)%mod)%mod;
for(int i=j+1;i<=pcnt && 1ll*prime[i]*prime[i]<=x;++i){
for(ll e=1,sp=prime[i];sp<=x;sp*=prime[i],++e)
ret=(ret+1ll*(prime[i]^e)*(S(x/sp,i)+(e>1))%mod)%mod;
}
return ret;
}
signed main(){
n=readin(1ll);sqn=sqrt(n);
if(n==1)return writc(1,'\n'),0;
sieve(sqn);
hash_w();
getg();
writc(S(n,0)+3,'\n');
return 0;
}
用到の小 \(\tt trick\)
先将所有的 \(f_0\) 都当成一样的,然后再补上 \(f(2)\) 产生的贡献.