莫比乌斯函数和欧拉函数
首先这两个函数第一项都是\(1\)
两个重要的式子
\[n=\sum\limits_{d|n}^{}\varphi(d)
\]
这个证明可以把所有的数写出来放到分子上,分母都是\(n\),然后约分,得到的就是所有因子的欧拉函数
可以证明是积性函数,于是我们证明对于质数的幂成立即可,写出来就成立了
然后这个东西非常神奇,我们用莫比乌斯反演演回去
\[\varphi(n)=\sum_{d|n}d*\mu(\frac{n}{d})
\]
于是我们得到了一个式子
\[\varphi=id*\mu
\]
这里是狄利克雷卷积,妙极了!!!这也是这两个函数之间的关系
\[\sum\limits_{d|n}^{}\mu(d)=[n==1]
\]
这个可以用二项式定理证明,所有不等于\(1\)的数的和都是\(0\)
线性筛
欧拉函数质数是\(p[i]-a\),没有重复因子的时候乘\(p[i]-1\),有重复因子的时候乘\(p[i]\)
code
phi[1]=sum[1]=1;fo(i,2,R){
if(!vis[i])p[++cnt]=i,phi[i]=i-1;
for(int j=1;j<=cnt&&p[j]*i<=R;j++){
vis[i*p[j]]=true;
if(i%p[j]==0){phi[i*p[j]]=phi[i]*p[j]%mod;break;}
else phi[i*p[j]]=phi[i]*(p[j]-1)%mod;
}
}
莫比乌斯函数质数是\(-1\),有重复因子就变成\(0\),没有的时候则乘\(-1\);
code
mu[1]=smu[1]=1;
fo(i,2,R){
if(!vis[i])p[++cnt]=i,mu[i]=-1;
for(int j=1;j<=cnt&&p[j]*i<=R;j++){
vis[i*p[j]]=true;
if(i%p[j]==0){mu[i*p[j]]=0;break;}
else mu[i*p[j]]=-mu[i];
}
}
杜教筛前缀和
欧拉函数,利用重要式子,卷上一个\(1\)函数(就是啥都是1的那个函数)。
\[S(n)=\sum_{i=1}^{n}\varphi(i)=\frac{n\cdot(n+1)}{2}-\sum_{i=2}^n\sum_{j=1}^{\lfloor\frac{n}{i}\rfloor}\varphi(j)=\frac{n\cdot(n+1)}{2}-\sum_{i=2}^nS(\lfloor\frac{n}{i}\rfloor)
\]
莫比乌斯函数,也是上面那个重要式子,也卷上一个\(1\)函数
\[S(n)=1-\sum_{i=2}^{n}S(\lfloor\frac{n}{i}\rfloor)
\]
杜教筛的时候直接递归下去,复杂度是\(\mathcal{O(n^{\frac{3}{2}})}\)
code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
const int N=1e6+5;
int n,ans,R=1e6;bool vis[N];
int p[N],cnt,phi[N],sph[N],mu[N],smu[N];
map<int,int> mph,mmu;
int ma(int n){
if(n<=R)return smu[n];
if(mmu.find(n)!=mmu.end())return mmu[n];
int ret=1;
for(int l=2,r;l<=n;l=r+1){
r=n/(n/l);
ret=ret-(r-l+1)*ma(n/l);
}
mmu[n]=ret;return ret;
}
int ph(int n){
if(n<=R)return sph[n];
if(mph.find(n)!=mph.end())return mph[n];
int ret=n*(n+1)/2;
for(int l=2,r;l<=n;l=r+1){
r=n/(n/l);
ret=ret-(r-l+1)*ph(n/l);
}
mph[n]=ret;return ret;
}
signed main(){
int T;scanf("%lld",&T);
phi[1]=sph[1]=mu[1]=smu[1]=1;
fo(i,2,R){
if(!vis[i])p[++cnt]=i,phi[i]=i-1,mu[i]=-1;
for(int j=1;j<=cnt&&p[j]*i<=R;j++){
vis[i*p[j]]=true;
if(i%p[j]==0){phi[i*p[j]]=phi[i]*p[j];mu[i*p[j]]=0;break;}
else phi[i*p[j]]=phi[i]*(p[j]-1),mu[i*p[j]]=-mu[i];
}
sph[i]=sph[i-1]+phi[i];
smu[i]=smu[i-1]+mu[i];
}
while(T--){
scanf("%lld",&n);
printf("%lld %lld\n",ph(n),ma(n));
}
}
技巧
关于欧拉函数,我们一般考虑是否有重复因子,可以试着把重复的先提出来!!
关于莫比乌斯函数,我们可以考虑因子个数,来找到容斥关系
\[\sum\limits_{d|n}^{}f(n)=\sum\limits_{d|n}^{}f(\frac{n}{d})
\]
上面这个东西换好了,一切都变得简单起来
有时候积性函数组成中包含莫比乌斯函数,那么可以拆成所有质因子\(p_i^{a_i}\)的函数值的乘积
这样的话,因为莫比乌斯函数的性质,在单独的质因子中,只有\(1\)和\(p_i\)有用,可以利用这个式子来简化计算
说实话,化简式子的过程就是不断的交换顺序......然而我不会
有时候可以先扩大一下范围,再找另外一个变量给它缩小回来
QQ:2953174821