莫比乌斯反演略解

莫比乌斯反演,又称懵逼钨丝繁衍

一、莫比乌斯函数

学莫比乌斯反演之前要学一下莫比乌斯函数
设正整数N珂以分解质因数成\(N=p_1^{c_1}p_2^{c_2}…p_m^{c_m}\)
定义莫比乌斯函数,记做\(\mu(N)\)

\[ \mu(x) = \left\{ \begin{aligned} 0 \qquad \qquad \qquad \qquad \ \exists i \in [1,m] , c_i>1\\ 1 \qquad m \equiv 0 (mod 2) , \forall i \in [1,m] , c_i=1 \\ -1 \qquad m \equiv 1 (mod 2) , \forall i \in [1,m] , c_i=1 \end{aligned} \right. \]

通俗的讲,当N包含相等的质因子时,\(\mu (N)=0\)。当N的所有质因子各不相等时,若N有偶数个质因子,\(\mu (N)=1\),若N有奇数个质因子\(\mu (N)=-1\)

下面我们来讲讲如何求莫比乌斯函数

当只需要求一项莫比乌斯函数时,则珂以用分解质因数(试除法或pollard's Rho)
若求1~N的每一项的莫比乌斯函数,我们珂以用筛法来计算(还在上面那篇文章中)。先把所有的\(\mu\)值初始化为1.接下来,对于筛出的每一个质数p,令\(\mu (p) = -1\),并扫描p的倍数\(x=2p,3p,…,\lfloor n/p \rfloor *p\),检查x能否被\(p^2\)整除。若能,则令\(\mu (x) = 0\),否则令\(\mu (x) = -\mu (x)\)
for(register int i=1;i<=n;++i)
    miu[i]=1,v[i]=0;
for(register int i=2;i<=n;++i)
{
    if(v[i])
        continue;
    miu[i]=-1;
    for(register int j=i<<1;j<=n;j+=i)
    {
        v[j]=1;
        if((j/i)%i==0)
            miu[j]=0;
        else
            miu[j]*=-1;
    }
}

2、莫比乌斯反演公式

莫比乌斯反演分为两种形式

形式1:

若函数F(x)和f(x)满足
\[F(n)=\sum_{d|n}f(d)\]
那么就有
\[f(n)=\sum_{d|n}\mu(d)F(\frac{n}{d})\]

形式2:

若函数F(x)和f(x)满足
\[F(n)=\sum_{n|d}f(d)\]
那么就有
\[f(n)=\sum_{n|d}\mu(\frac{d}{n})F(d)\]

两条性质

我们需要运用这两条性质来证明莫比乌斯反演

性质1:

对于任何正整数n有
\[ \ \sum_{d|n}\mu(d) = \left\{ \begin{aligned} 1 \qquad (n=1) \\ 0 \qquad (n>1) \end{aligned} \right. \]
证明:
1.当n=1时显然成立
2、在n>1时,珂以讲n分解成\(n=p_1^{c_1}p_2^{c_2}…p_m^{c_m}\)
在n的所有因子中,\(\mu\)的值不为零的只有所有质因子次数为都1的因子,其中质因数个数为r个的因子有\(C_m^r\)
那么显然有:
\[\sum_{d|n}\mu(d)=C_m^0-C_m^1+C_m^2+…+(-1)^mC_m^m=\sum_{i=0}^m(-1)^iC_m^i\]
所以我们要证明\(\sum_{i=0}^m(-1)^iC_m^i\)
根据二项式定理:
\[(x+y)^n=\sum_{i=0}^nC_n^ix^iy^{n-i}\]
将x=1,y=-1带入即珂以得证

性质2:

\[\sum_{d|n}\frac{\mu(d)}{d}=\frac{\varphi(n)}{n}\]
证明珂以直接带入反演公式

莫比乌斯反演证明

懒着写了

莫比乌斯反演的应用

讲了那么多,最后也只是记住形式
所以我们结合Luogu P3455 [POI2007]ZAP-Queries来讲一下莫比乌斯反演的应用
题目大意:求对于区间\([1,a]\)内的整数x和\([1,b]\)内的y,满足\(gcd(x,y)=d\)的数对的个数
设F(t)表示满足gcd(x,y)%t=0的数对个数,f(t)表示满足\(gcd(x,y)=t\)的数对个数,实际上答案就是f(d)
这就满足莫比乌斯反演的关系式了
显然我们珂以得知\(F(t)=(b/t)*(d/t)\)
我们根据反演的第二个公式便珂以得出
\[f(d)=\sum_{n|d}\mu(\frac{d}{n})F(d)\]
还有一个叫整除分块的小技巧
大体长这样
for(register int l=1,r;l<=n;l=r+1)
{
    r=n/(n/l);
    ans+=(r-l+1)*(n/l);
}
就这样就过了qaq
#include <bits/stdc++.h>
#define N 50005
#define ll long long 
#define getchar nc
using namespace std;
inline char nc(){
    static char buf[100000],*p1=buf,*p2=buf; 
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 
}
inline int read()
{
    register int x=0,f=1;register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*f;
}
inline void write(register ll x)
{
    if(!x)putchar('0');if(x<0)x=-x,putchar('-');
    static int sta[30];register int tot=0;
    while(x)sta[tot++]=x%10,x/=10;
    while(tot)putchar(sta[--tot]+48);
}
inline int Min(register int x,register int y)
{
    return x<y?x:y;
}
int v[N],miu[N],sum[N];
int main()
{
    for(register int i=1;i<=N;++i)
        miu[i]=1,v[i]=0;
    for(register int i=2;i<=N;++i)
    {
        if(v[i])
            continue;
        miu[i]=-1;
        for(register int j=i<<1;j<=N;j+=i)
        {
            v[j]=1;
            if((j/i)%i==0)
                miu[j]=0;
            else
                miu[j]*=-1;
        }
    }
    for(register int i=1;i<=N;++i)
        sum[i]=sum[i-1]+miu[i];
    int t=read();
    while(t--)
    {
        int a=read(),b=read(),d=read();
        int maxround=Min(a/d,b/d);
        ll ans=0;
        for(register int l=1,r;l<=maxround;l=r+1)
        {
            r=Min((a/d)/((a/d)/l),(b/d)/((b/d)/l));
            ans+=(ll)((a/d)/l)*((b/d)/l)*(sum[r]-sum[l-1]); 
        }   
        write(ans),puts("");
    }
    return 0;
}

转载于:https://www.cnblogs.com/yzhang-rp-inf/p/10124488.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值