要线性筛的时候可以这样子想:两个积性函数卷起来肯定是积性函数。
那么我们只需要知道g[p^r]就可以了。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 10000050 using namespace std; int t,n,prime[maxn/10],tot=0,r[maxn],phi[maxn]; long long g[maxn]; bool vis[maxn]; void get_table() { g[1]=r[1]=phi[1]=1; for (int i=2;i<=maxn-50;i++) { if (!vis[i]) { prime[++tot]=i; g[i]=i-2;r[i]=i;phi[i]=i-1; } for (int j=1;j<=tot && i*prime[j]<=maxn-50;j++) { vis[i*prime[j]]=true; if (!(i%prime[j])) { r[i*prime[j]]=r[i]*prime[j];phi[i*prime[j]]=phi[i]*prime[j]; g[i*prime[j]]=g[i*prime[j]/r[i*prime[j]]]*(long long)(phi[r[i*prime[j]]]-phi[r[i*prime[j]]/prime[j]]); break; } r[i*prime[j]]=prime[j];phi[i*prime[j]]=phi[i]*(prime[j]-1); g[i*prime[j]]=g[i]*g[prime[j]]; } } for (int i=1;i<=maxn-50;i++) g[i]+=g[i-1]; } int main() { scanf("%d",&t);get_table(); for (int i=1;i<=t;i++) { scanf("%d",&n); int l=1,r; long long ans=0; while (l<=n) { r=n/(n/l); ans+=(long long)(n/l)*(n/l)*(g[r]-g[l-1]); l=r+1; } printf("%lld ",ans); } return 0; }