转自:
1. 求$sumlimits_{i=1}^nmu(i),nleqslant 10^{11}$
直接求不好求,但是我们有$sumlimits_{i=1}^nsumlimits_{d|i}mu(d)=1$
化一下蛤:$sumlimits_{i=1}^nsumlimits_{j=1}^{leftlfloorfrac{n}{i}
ight
floor}mu(j)=1$,$sumlimits_{i=1}^nmu(i)=1-sumlimits_{i=2}^nsumlimits_{j=1}^{leftlfloorfrac{n}{i}
ight
floor}mu(j)$
核心思想是枚举约数,这样就可以递推/递归求解了。
时间复杂度$Oleft(n^{frac34}
ight)$。
但是注意到当$n$比较小的时候其实我们可以$O(n)$线筛出来。
所以我们考虑分类讨论,线筛出≤B的,>B的递推。
时间复杂度$Oleft(B+sumlimits_{i=1}^{frac nB}sqrt{frac ni}
ight)=Oleft(B+frac n{sqrt{B}}
ight)$
求导一下可知在$B=n^{frac23}$时取得最小值$Oleft(n^frac23 ight)$。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<map> 6 #define ll long long 7 #define N 5000005 8 using namespace std; 9 const int inf = 5000000; 10 map<int,ll>mp; 11 int su[N],pr[N],tot; 12 ll f[N]; 13 void shai() 14 { 15 f[1]=1; 16 for(int i=2;i<=inf;i++) 17 { 18 if(!pr[i]) 19 { 20 pr[i]=i; 21 su[++tot]=i; 22 f[i]=i-1; 23 } 24 for(int j=1;j<=tot&&su[j]<=pr[i]&&su[j]*i<=inf;j++) 25 { 26 pr[su[j]*i]=su[j]; 27 if(su[j]==pr[i])f[su[j]*i]=f[i]*su[j]; 28 else f[su[j]*i]=f[i]*(su[j]-1); 29 } 30 } 31 for(int i=1;i<=inf;i++) 32 { 33 f[i]=f[i-1]+f[i]; 34 } 35 return ; 36 } 37 int n; 38 ll phi(int x) 39 { 40 if(x<=inf)return f[x]; 41 if(mp.find(x)!=mp.end())return mp[x]; 42 ll as=1LL*x*(x+1)/2;int r; 43 for(int l=2;l<=x;l=r+1) 44 { 45 r=x/(x/l); 46 as-=phi(x/l)*(r-l+1); 47 } 48 return mp[x]=as; 49 } 50 int main() 51 { 52 shai(); 53 scanf("%d",&n); 54 printf("%lld ",phi(n)); 55 return 0; 56 } 57