莫比乌斯反演的前置知识:https://www.cnblogs.com/yyc-jack-0920/p/10556351.html

杜教筛可以在$O(n^{2/3})$的时间内求出积性函数的前缀和即$\sum\limits_{i=1}^n f(i)$

实现过程需要找到另一个积性函数$g$使得$f*g$为一个方便计算的函数

$\sum f*g=\sum\limits_{i=1}^n \sum\limits_{d|i} g(d)f(i/d) $

                $=\sum\limits_{d=1}^n g(d) \sum\limits_{t=1}^{n/d} f(t)$

                $=g(1)\sum\limits_{i=1}^n f(i) + \sum\limits_{d=2}^n g(d) \sum\limits_{i=1}^{n/d} f(i)$

设前缀和为$S(i)$ 即$g(1)S(n)=-\sum\limits_{d=2}^n g(d) S(n/d)+\sum f*g$

这样就写成了一个数论分块的递归形式,复杂度可以证明(

同时,由于杜教筛自带数论分块形式,因此在外面再套一层数论分块并不会影响复杂度

 

luogu 4213 【模板】杜教筛:

求$\varphi$与$\mu$的前缀和

有结论:$\varphi*1=id$、$\mu *1 =[n=1]$ 直接套用公式即可

 1 #include<bits/stdc++.h>
 2 #define inf 2139062143
 3 #define MAXN 5001001
 4 #define MOD 1000000007
 5 #define ll long long
 6 #define ull unsigned long long
 7 #define rep(i,s,t) for(register int i=(s),i##end=(t);i<=i##end;++i)
 8 #define dwn(i,s,t) for(register int i=(s),i##end=(t);i>=i##end;--i)
 9 #define ren for(register int i=fst[x];i;i=nxt[i])
10 #define Fill(a,b) memset(a,b,sizeof(a))
11 #define pls(a,b) ((a+b)%MOD+MOD)%MOD
12 #define mns(a,b) (((a)-(b))%MOD+MOD)%MOD
13 #define mul(a,b) (1LL*(a)*(b)%MOD)
14 #define pii pair<int,int>
15 #define mp(a,b) make_pair(a,b)
16 #define pb(i,x) vec[i].push_back(x)
17 #define fi first
18 #define se second
19 using namespace std;
20 inline ll read()
21 {
22     ll x=0;bool f=1;char ch=getchar();
23     while(!isdigit(ch)) {if(ch=='-') f=0;ch=getchar();}
24     while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
25     return f?x:-x;
26 }
27 int lmt,ntp[MAXN],p[MAXN],tot;ll mu[MAXN],phi[MAXN];
28 void mem(int n)
29 {
30     mu[1]=phi[1]=1;rep(i,2,n)
31     {
32         if(!ntp[i]) p[++tot]=i,mu[i]=-1,phi[i]=i-1;
33         rep(j,1,tot) if(1LL*i*p[j]>n) break;
34             else
35             {
36                 ntp[i*p[j]]=1;if(i%p[j]) mu[i*p[j]]=-mu[i],phi[i*p[j]]=phi[i]*phi[p[j]];
37                 else {phi[i*p[j]]=phi[i]*p[j];break;}
38             }
39     }
40     rep(i,1,n) mu[i]+=mu[i-1],phi[i]+=phi[i-1];
41 }
42 unordered_map<int,ll> ansm,ansp;
43 ll smu(ll n,ll res=0)
44 {
45     if(n<=lmt) return mu[n];if(ansm[n]) return ansm[n];
46     for(ll l=2,r;l<=n;l=r+1) r=n/(n/l),res+=smu(n/l)*(r-l+1);
47     return ansm[n]=1LL-res;
48 }
49 ll sphi(ll n,ll res=0)
50 {
51     if(n<=lmt) return phi[n];if(ansp[n]) return ansp[n];
52     for(ll l=2,r;l<=n;l=r+1) r=n/(n/l),res+=sphi(n/l)*(r-l+1);
53     return ansp[n]=1LL*n*(n+1)/2-res;
54 }
55 int main()
56 {
57     int T=read(),n;mem(lmt=5000000);
58     while(T--) {n=read();printf("%lld %lld\n",sphi(n),smu(n));}
59 }
View Code

相关文章: