#4704. 求和

题目描述

题解

化式子:
$$f_n=\sum_{d|n}d\sum_{i=1}^{\frac{n}{d}}\sum_{j=1}^{\frac{n}{d}}[gcd(i,j,\frac{n}{d})=1]$$
$$=\sum_{d|n}d\sum_{x|\frac{n}{d}}\mu(x)(\frac{n}{dx})^2$$
设 $g=dx$ ,接着化
$$=\sum_{g|n}(\frac{n}{g})^2\sum_{d|g}\mu(\frac{g}{d})d$$
$$=\sum_{g|n}(\frac{n}{g})^2\phi(g)$$
于是得到$$S_N=\sum_{n=1}^Nf_n=\sum_{n=1}^N\sum_{g|n}(\frac{n}{g})^2\phi(g)$$
$$=\sum_{g=1}^N\phi(g)\sum_{i=1}^{\frac{n}{g}}i^2$$
后面那项数论分块,$\phi$的前缀和用杜教筛求即可

代码

#include <bits/stdc++.h>
using namespace std;
const int N=5e6+5;
int n,pr[N],tp,T,fi[N],P,I,s,V;
bool vis[N];map<int,int>_fi;
int K(int x,int y){
    int z=1;
    for (;y;y>>=1,x=1ll*x*x%P)
        if (y&1) z=1ll*z*x%P;
    return z;
}
void init(){
    fi[1]=1;
    for (int i=2;i<N;i++){
        if (!vis[i]) pr[++tp]=i,fi[i]=i-1;
        for (int j=1;j<=tp && pr[j]*i<N;j++){
            vis[i*pr[j]]=1;
            if (i%pr[j]) fi[i*pr[j]]=fi[i]*fi[pr[j]];
            else{fi[i*pr[j]]=fi[i]*pr[j];break;}
        }
    }
    for (int i=1;i<N;i++) (fi[i]+=fi[i-1])%=P;
}
int Fi(int x){
    if (x<N) return fi[x];
    if (_fi.count(x)) return _fi[x];int v=0;
    for (int l=2,r;l<=x;l=r+1)
        r=x/(x/l),(v+=1ll*(r-l+1)*Fi(x/l)%P)%=P;
    return _fi[x]=(1ll*x*(x+1)%P*I%P-v+P)%P;
}
int C(int x){
    return 1ll*x*(x+1)%P*(x+x+1)%P*V%P;
}
int main(){
    cin>>n>>P;I=K(2,P-2);V=K(6,P-2);init();
    for (int l=1,r;l<=n;l=r+1)
        r=n/(n/l),(s+=1ll*(Fi(r)-Fi(l-1)+P)*C(n/l)%P)%=P;
    cout<<s<<endl;return 0;
}

 

posted @ 2020-02-05 13:33  xjqxjq  阅读(136)  评论(0编辑  收藏  举报