题解:杜教筛
问题:式子推的不熟
#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;
}