[BZOJ4916]神犇和蒟蒻

题目

让你计算俩东西:

\[A=\sum_{i=1}^n\mu(i^2)\\ B=\sum_{i=1}^n\varphi(i^2) \]

数据范围:\(n\le 10^9\).

题解

不难发现 \(A=1\).

对于 \(B\) 而言,可以感性理解,发现 \(\varphi(i^2)=i\times \varphi(i)\),即我们需要计算

\[B=\sum_{i=1}^ni\times \varphi(i) \]

\(f(i)=i\times \varphi(i)\),那么有

\[\begin{aligned} f*g=\sum_{d|n}d\cdot \varphi(d)\cdot g(\frac{n}{d}) \end{aligned} \]

这个 \(d\) 有些不爽,我们尝试构造 \(g(\frac{n}{d})\) 将其消掉,定义 \(g(\frac{n}{d})=\frac{n}{d}\)\(g=id\),那么有

\[\begin{aligned} f*g&=\sum_{d|n}d\cdot \varphi(d)\cdot \frac{n}{d} \\ &=\sum_{d|n}n\cdot \varphi(d) \\ &=n\sum_{d|n}\varphi(d)=n^2 \end{aligned} \]

也有 \(h(i)=i^2\),而我们有

\[\sum_{i=1}^nh(i)=\frac{n(n+1)(2n+1)}{6} \]

带入杜教筛公式,有

\[B=\frac{n(n+1)(2n+1)}{6}-\sum_{i=2}^ng(i)\cdot f(\left\lfloor\frac{n}{i}\right\rfloor) \]

数论分块即可.

代码

const int mod=1e9+7;
const int maxn=2e6;
const int inv6=166666668;

int phi[maxn+5];
int prime[maxn>>2],pcnt;
inline void sieve(){
    phi[1]=1;
    rep(i,2,maxn){
        if(!phi[i])prime[++pcnt]=i,phi[i]=i-1;
        for(int j=1;j<=pcnt && i*prime[j]<=maxn;++j){
            if(i%prime[j]==0){
                phi[i*prime[j]]=1ll*phi[i]*prime[j]%mod;
                break;
            }
            phi[i*prime[j]]=1ll*phi[i]*phi[prime[j]]%mod;
        }
    }
    rep(i,1,maxn)phi[i]=(1ll*i*phi[i]+phi[i-1])%mod;
}

int n;

inline int func(const int n){
    return (1ll*n*(n+1)%mod*(2*n+1)%mod*inv6)%mod;
}

map<int,ll>memo;

inline int calc(const int l,const int r){
    return (1ll*(r-l+1)*(l+r)/2)%mod;
}

int getS(const int n){
    if(n<=maxn)return phi[n];
    if(memo[n])return memo[n];
    int ret=func(n);
    for(int l=2,r;l<=n;l=r+1){
        r=n/(n/l);
        ret=(ret+mod-1ll*calc(l,r)*getS(n/l)%mod)%mod;
    }
    return memo[n]=ret;
}

signed main(){
    // freopen("shit.out","w",stdout);
    n=readin(1);
    writc(1,'\n');
    sieve();
    writc(getS(n),'\n');
    return 0;
}
posted @ 2021-01-31 18:01  Arextre  阅读(54)  评论(0编辑  收藏  举报