标签:sum cstring turn using pen 解法 i++ stream indicator
题意:
求解$\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) = \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 }
标签:sum cstring turn using pen 解法 i++ stream indicator
原文地址:http://www.cnblogs.com/lawyer/p/6446062.html