传送门
线性筛+分块水过。
解释:
输出前的ans是严格满足j<=i的,所以要乘二,对角线又重复出现,所以要减去。
#include<cstring>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#define ll long long
#define N 10000005
using namespace std;
ll phi[N],ans;
int vis[N],pri[N/10],n,T,tot;
int main(){
phi[1]=1;
for (int i=2;i<N;i++){
if (!vis[i]) phi[i]=i-1,pri[++tot]=i;
for (int j=1;j<=tot&&i*pri[j]<N;j++){
vis[i*pri[j]]=1;
if (i%pri[j]==0){
phi[i*pri[j]]=phi[i]*pri[j];
break;
}
phi[i*pri[j]]=phi[i]*(pri[j]-1);
}
}
for (int i=2;i<N;i++)
phi[i]+=phi[i-1];
scanf("%d",&T);
while (T--){
scanf("%d",&n);
ans=0;
for (int i=1,j;i<=n;i=j+1){
j=n/(n/i);
ans+=phi[n/i]*(phi[j]-phi[i-1]);
}
printf("%lld\n",ans*2-phi[n]);
}
}