转化一下,$\sum\limits_{i=1}^n[i,n]=n\sum\limits_{i=1}^n\dfrac i{(i,n)}$
枚举$d=(i,n)$,上式变为$n\sum\limits_{d=1}^n\sum\limits_{i=1}^n[(i,n)=d]\dfrac id=n\sum\limits_{d|n}\sum\limits_{i=1}^{\frac nd}\left[\left(i,\dfrac nd\right)=1\right]i$
设$f(n)=\sum\limits_{i=1}^n[(i,n)=1]i$,即互质数和
$$\begin{align*}f(n)&=\sum\limits_{i=1}^ni\sum\limits_{d|(i,n)}\mu(d)\\&=\sum\limits_{d|n}\mu(d)\sum\limits_{\substack{d|i\\i\leq n}}i\\&=\sum\limits_{d|n}d\mu(d)\sum\limits_{i=1}^{\frac nd}i\\&=\dfrac n2\sum\limits_{d|n}\mu(d)\left(\dfrac nd+1\right)\\&=\dfrac n2\left([n=1]+\sum\limits_{d|n}\mu(d)\dfrac nd\right)\\&=\dfrac n2\left([n=1]+\varphi(n)\right)\end{align*}$$
最后一步转变的依据可以用$n=\sum\limits_{d|n}\varphi(d)$反演得到
于是我们可以$O(1)$算$f(n)$了,原式变成$n\sum\limits_{d|n}f\left(\dfrac nd\right)=n\sum\limits_{d|n}f(d)$,$O(\sqrt n)$枚举约数就好了
#include<stdio.h> #define ll long long #define T 1000000 int phi[1000010],pr[1000010]; bool np[1000010]; void sieve(){ int i,j,m=0; np[1]=1; phi[1]=1; for(i=2;i<=T;i++){ if(!np[i]){ m++; pr[m]=i; phi[i]=i-1; } for(j=1;j<=m;j++){ if(pr[j]*(ll)i>T)break; np[i*pr[j]]=1; if(i%pr[j]==0){ phi[i*pr[j]]=phi[i]*pr[j]; break; }else phi[i*pr[j]]=phi[i]*(pr[j]-1); } } } ll f(int n){return(phi[n]+(n==1))*(ll)n/2;} int main(){ sieve(); int t,i,n; ll s; scanf("%d",&t); while(t--){ scanf("%d",&n); s=0; for(i=1;i*i<=n;i++){ if(n%i==0){ s+=f(n/i); if(i*i<n)s+=f(i); } } printf("%lld\n",n*s); } }