杜教筛 模板

转自:

 http://blog.leanote.com/post/totziens/%E8%8E%AB%E6%AF%94%E4%B9%8C%E6%96%AF%E5%8F%8D%E6%BC%94%E4%B8%8E%E6%9D%9C%E6%95%99%E7%AD%9B

1. 求$\sum\limits_{i=1}^n\mu(i),n\leqslant 10^{11}$
直接求不好求,但是我们有$\sum\limits_{i=1}^n\sum\limits_{d|i}\mu(d)=1$
化一下蛤:$\sum\limits_{i=1}^n\sum\limits_{j=1}^{\left\lfloor\frac{n}{i}\right\rfloor}\mu(j)=1$,$\sum\limits_{i=1}^n\mu(i)=1-\sum\limits_{i=2}^n\sum\limits_{j=1}^{\left\lfloor\frac{n}{i}\right\rfloor}\mu(j)$
核心思想是枚举约数,这样就可以递推/递归求解了。
时间复杂度$O\left(n^{\frac34}\right)$。
但是注意到当$n$比较小的时候其实我们可以$O(n)$线筛出来。
所以我们考虑分类讨论,线筛出≤B的,>B的递推。
时间复杂度$O\left(B+\sum\limits_{i=1}^{\frac nB}\sqrt{\frac ni}\right)=O\left(B+\frac n{\sqrt{B}}\right)$

求导一下可知在$B=n^{\frac23}$时取得最小值$O\left(n^\frac23\right)$。

 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\n",phi(n));
55     return 0;
56 }
57 

 

 

转载于:https://www.cnblogs.com/ezyzy/p/6679971.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值