题解:杜教筛
问题:式子推的不熟
#include<iostream> #include<cstdio> #include<cstring> #include<map> using namespace std; typedef long long Lint; int n; map<int,Lint>f; int cntprime; int prime[1000009]; int vis[10000009]; Lint phi[10000009]; void Lineshake(){ phi[1]=1;vis[1]=1; for(int i=2;i<=10000000;++i){ if(!vis[i]){ prime[++cntprime]=i; phi[i]=i-1; } for(int j=1;(j<=cntprime)&&(i*prime[j]<=10000000);++j){ vis[i*prime[j]]=1; if(i%prime[j]==0){ phi[i*prime[j]]=phi[i]*prime[j]; break; } phi[i*prime[j]]=phi[i]*(prime[j]-1); } } for(int i=2;i<=10000000;++i)phi[i]+=phi[i-1]; } Lint Calc(int n){ if(n<=10000000)return phi[n]; if(f.count(n))return f[n]; Lint ret=n*1LL*(n+1)/2; int last; for(int d=2;d<=n;d=last+1){ last=n/(n/d); ret-=(last-d+1)*Calc(n/d); } f[n]=ret; return ret; } int main(){ scanf("%d",&n); Lineshake(); cout<<Calc(n); return 0; }