莫比乌斯函数

在数论中的积性函数:对于正整数n的一个算术函数 f(n),若f(1)=1,且当a,b互质时f(ab)=f(a)f(b),在数论上就称它为积性函数。若对于某积性函数 f(n) ,就算a, b不互质,也有f(ab)=f(a)f(b),则称它为完全积性的。


φ(n) -欧拉函数,计算与n互质的正整数之数目
μ(n) -莫比乌斯函数,关于非平方数的质因子数目
莫比乌斯函数完整定义的通俗表达:
1)莫比乌斯函数μ(n)的定义域是N
2)μ(1)=1
3)当n存在平方因子时,μ(n)=0
4)当n是素数或奇数个不同素数之积时,μ(n)=-1
5)当n是偶数个不同素数之积时,μ(n)=1


莫比乌斯函数,数论函数,由德国数学家和天文学家莫比乌斯(August Ferdinand Möbius ,1790–1868)提出。梅滕斯(Mertens)首先使用μ(n)作为莫比乌斯函数的记号。而据说,高斯(Gauss)比莫比乌斯早三十年就曾考虑过这个函数。莫比乌斯函数在数论中有着广泛应用。

设f为算术函数,F为f的和函数,有F(n)=sigma[f(d)],d|n。我们现在要做的事是如何根据F求出f。

例如:

F(1)=f(1)

F(2)=f(1)+f(2)

F(3)=f(1)+f(3)

F(4)=f(1)+f(2)+f(4)

F(5)=f(1)+f(5)

F(6)=f(1)+f(2)+f(3)+f(6)

F(7)=f(1)+f(7)

F(8)=f(1)+f(2)+f(4)+f(8)

利用解方程,我们得到:

f(1)=F(1)

f(2)=F(2)-F(1)

f(3)=F(3)-F(1)

f(4)=F(4)-F(2)

f(5)=F(5)-F(1)

f(6)=F(6)-F(3)-F(2)+F(1)

f(7)=F(7)-F(1)

f(8)=F(8)-F(4)

观察发现,f(n)等于形式为+/-F(n/d),d|n,所以我们推论出莫比乌斯反演公式:

f(n)=sigma[u(d)*F(n/d)](一定要记住这个形式呀,否则后面你就不好理解了)。

现在试着确定u函数:

例如,对于上面的例子有u(1)=u(6)=1, u(2)=u(3)=u(5)=u(7)=-1,u(4)=u(8)=0。

继续观察:

若p是素数

F(p)=f(1)+f(p)=>f(p)=F(p)-F(1),那么u(p)=-1。

继续观察:

F(p^2)=f(1)+f(p)+f(p^2)=>f(p^2)=F(p^2)-(F(p)-F(1))-F(1)=F(p^2)-F(p),这又有u(p^2)=0。

同理我们推出f(p^3)=F(p^3)-F(p^2),这又有u(p^3)=0,就这样推下去,我们有当k>1,有u(p^k)=0。

继续观察:

设p1,p2为素数

F(p1*p2)=f(p1*p2)+f(p1)+f(p2)+f(1)=>f(p1*p2)=F(p1*p2)-F(p1)-F(p2)+F(1)。

这里有u(1)=1, u(p2)=-1,u(p1)=-1,u(p1*p2)=1。

如果不嫌累,你就在继续推,以下直接给出莫比乌斯函数了(要是一一列举得累死我)。

u(n) = 1 如果n=1

= (-1)^r 如果n=p1*p2*......pr,其中pi为各不相同的素数

= 0 其它

行了,莫比乌斯函数有很多性质呢。就不证明了,只给出这些性质吧。

(1)莫比乌斯函数是乘性函数

(2)设F(n)=sigma[u(d)],d|n,如果n=1,则F(n)=1,若n>1则等于0。

至于如何去验证莫比乌斯函数确实能够达到反演的大家就自己研究吧。

并且若f的和函数F是乘性的,我们可以根据莫比乌斯反演推出f也是乘性的。

好了,看看利用莫比乌斯反演公式能得到什么好玩的。

设f1(n)=n,f2(n)=1

F1(n)=sigma(f1(d)), d|n1

F2(n)=sigma(f2(d)), d|n2

那么根据反演公式有

n=sigma[u(n/d)*F1(d)]

1=sigma[u(n/d)*F2(d)]

很神奇,是吧。

还有呢

若f是欧拉函数,则f(n)=n*(sigma[u(d)/d]),d|n。


今天终于把莫比乌斯看明白了,但证明貌似还是无力。

acdream



设f(d) 表示gcd为d的倍数的数的对数

g(d)表示gcd恰好为d的数的对数

f(d) = ∑ g(n) (n % d == 0)

g(d) = ∑  mu[n / d] * f(n) (n %d == 0)

上面两个式子就是套路,没啥难的

所以 g(1) = ∑mu[n] * f(n)

求一下mu[ ],枚举一下n就可以AC了

方法一:莫比乌斯反演

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace  std;
const int maxn=222232;
int mu[maxn],a[maxn],prime[maxn],cnt[maxn],num[maxn];
bool vis[maxn];
int n,pnum;
void mobius(int N)
{
    pnum=0;
    vis[1]=mu[1]=1;
    for(int i=2;i<=N;i++)
    {
        if(!vis[i])
        {
            mu[i]=-1;
            prime[pnum++]=i;
        }
        for(int j=0;j<pnum;j++)
        {
            if(i*prime[j]>N)break;
            vis[i*prime[j]]=1;//筛掉合数
            if(i%prime[j]==0)
            {
                mu[i*prime[j]]=0;
                break;//保证合数使用最小的素数筛掉的
            }
            mu[i*prime[j]]=-mu[i];
        }
    }
}
int main()
{
    //freopen("in.txt","r",stdin);
    mobius(222222);
    while(scanf("%d",&n)!=EOF)
    {
        int max1=0;
        memset(num,0,sizeof(num));
        memset(cnt,0,sizeof(cnt));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            num[a[i]]++;
            max1=max(max1,a[i]);
        }
        for(int i=1;i<=max1;i++)
            for(int j=i;j<=max1;j+=i)
            cnt[i]+=num[j];
        long long ans=0;
        for(int i=1;i<=max1;i++)
            ans+=((long long)cnt[i]*(cnt[i]-1)/2)*mu[i];
        printf("%lld\n",ans);
    }
    return 0;
}

方法二:跟莫比乌斯阿反演差不多,只不过是把它的倍数中重复计算的去掉了


#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
const int maxn=222232;
int cnt[maxn],n,x,max1;
LL ans[maxn];
void solve()
{
    //memset(ans,0,sizeof(ans));
    for(int i=2;i<=max1;i++)
    {
        ans[i]=0;
        for(int j=i;j<=max1;j+=i)ans[i]+=cnt[j];
    }
    for(int i=2;i<=max1;i++)ans[i]=ans[i]*(ans[i]-1)/2;
    for(int i=max1;i>1;i--)
        for(int j=2*i;j<=max1;j+=i)
            ans[i]-=ans[j];//把重复计算的去掉
    LL sum=0;
    for(int i=2;i<=max1;i++)sum+=ans[i];
    sum=(LL)n*(n-1)/2-sum;
    printf("%lld\n",sum);
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        memset(cnt,0,sizeof(cnt));
        max1=0;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&x);
            max1=max(max1,x);
            cnt[x]++;
        }
        solve();
    }
    return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值