莫比乌斯函数和欧拉函数

这篇

首先这两个函数第一项都是\(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}})}\)

Luogu4213 Sum

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\)有用,可以利用这个式子来简化计算

说实话,化简式子的过程就是不断的交换顺序......然而我不会

有时候可以先扩大一下范围,再找另外一个变量给它缩小回来

posted @ 2021-12-28 17:20  fengwu2005  阅读(322)  评论(0编辑  收藏  举报