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 }
View Code

 

同样的方法,由$(\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 }
View Code

 

posted @ 2017-02-26 21:44  lawyer'  阅读(241)  评论(0编辑  收藏  举报