#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; }