Mertens
题意:
求解$\sum_{i=a}^b{\mu(i)}$。
解法:
由$(\mu * I)(n) = e(n)$ 得 $\sum_{d|n}{\mu(d)} = [n=1]$ 得 $\mu(n) = \sum_{d|n,d<n}{\mu(d)}$
从而有$$\sum_{i=1}^n{\mu(i)} = 1 - \sum_{i=1}^n{ \sum_{d|i,d<i}{\mu(d)} }$$
$$=1-\sum_{t=2}^n{ \sum_{d=1}^{[\frac{n}{t}]}{\mu(d)} }$$
记$S(n) = \sum_{i=1}^n{\mu(i)}$
从而有$S(n) = 1- \sum_{t=2}^n{S([\frac{n}{t}])}$
考虑分块优化此式,产生$O(\sqrt n)$的时间复杂度,当n小于等于$n^{0.6667}$时直接应用线性筛计算。
分析得会产生$O(n^{0.667})$个n,从而应用map,递归计算即可。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <ctime> 5 #include <map> 6 7 #define LL long long 8 #define LIM 5000000 9 10 using namespace std; 11 12 int tot,prime[LIM+10]; 13 LL u[LIM+10]; 14 bool v[LIM+10]; 15 map<LL,LL> ansv; 16 17 LL S(LL n) 18 { 19 if(n<=LIM) return u[n]; 20 if(ansv.count(n)) return ansv[n]; 21 LL j; 22 LL ans=1; 23 for(LL i=2;i<=n;i=j+1) 24 { 25 j=n/(n/i); 26 ans -= (j-i+1LL) * S(n/i); 27 } 28 ansv[n]=ans; 29 return ans; 30 } 31 32 int main() 33 { 34 // freopen("test.txt","r",stdin); 35 u[1]=1; 36 for(int i=2;i<=LIM;i++) 37 { 38 if(!v[i]) 39 { 40 prime[++tot]=i; 41 u[i]=-1; 42 } 43 for(int j=1;i*prime[j]<=LIM;j++) 44 { 45 v[i*prime[j]]=1; 46 u[i*prime[j]]=u[i]*u[prime[j]]; 47 if(i%prime[j]==0) 48 { 49 u[i*prime[j]]=0; 50 break; 51 } 52 } 53 } 54 for(int i=2;i<=LIM;i++) u[i]+=u[i-1]; 55 LL a,b; 56 cin >> a >> b; 57 cout << S(b)-S(a-1) << endl; 58 return 0; 59 }
同样的方法,由$(\phi * I)(n) = id(n)$得到
$S(n) = \frac{n(n+1)}{2} - \sum_{t=2}^n{S([\frac{n}{t}])}$
注意n*(n+1)可能炸long long。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <ctime> 5 #include <map> 6 #include <cassert> 7 8 #define LL long long 9 #define LIM 5000000 10 #define P 1000000007LL 11 12 using namespace std; 13 14 int tot,prime[LIM+10]; 15 LL phi[LIM+10],inv2; 16 bool v[LIM+10]; 17 map<LL,LL> ansv; 18 19 LL S(LL n) 20 { 21 if(n<=LIM) return phi[n]; 22 if(ansv.count(n)) return ansv[n]; 23 LL j; 24 LL ans=n%P * (n%P + 1LL) %P * inv2%P; 25 assert(ans >=0); 26 for(LL i=2;i<=n;i=j+1) 27 { 28 j=n/(n/i); 29 ans += P - ((j-i+1LL) * S(n/i)%P); 30 if(ans>=P) ans -= P; 31 } 32 ansv[n]=ans; 33 return ans; 34 } 35 36 LL qpow(LL x,int n) 37 { 38 LL ans=1; 39 for(;n;n>>=1,x=x*x%P) if(n&1) ans=ans*x%P; 40 return ans; 41 } 42 43 int main() 44 { 45 // freopen("test.txt","r",stdin); 46 phi[1]=1; 47 for(int i=2;i<=LIM;i++) 48 { 49 if(!v[i]) 50 { 51 prime[++tot]=i; 52 phi[i]=i-1; 53 } 54 for(int j=1;i*prime[j]<=LIM;j++) 55 { 56 v[i*prime[j]]=1; 57 phi[i*prime[j]]=phi[i]*phi[prime[j]]; 58 if(i%prime[j]==0) 59 { 60 phi[i*prime[j]]=phi[i]*prime[j]; 61 break; 62 } 63 } 64 } 65 inv2=qpow(2,P-2); 66 for(int i=2;i<=LIM;i++) 67 { 68 phi[i]=phi[i]+phi[i-1]; 69 if(phi[i]>=P) phi[i] -= P; 70 } 71 LL n; 72 cin >> n; 73 cout << S(n) << endl; 74 return 0; 75 }