【模板】莫比乌斯反演

一、莫比乌斯反演

我们先来看一个函数:\(F(x)=\sum_{d\mid x} f(d)\)
我们先枚举一下这个函数的各个值

\(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(n)\)的关系式

\(f(1)=F(1)\)

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

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

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

\(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(x)=\sum_{d\mid x} f(d)\Rightarrow f(x)=\sum_{d\mid x}\mu(d)F(\frac{n}{d})\qquad\)

其中,我们可以了解到一个新的函数:莫比乌斯函数

二、莫比乌斯函数:\(\mu(x)\)

这是莫比乌斯函数,定义如下
  1. \(x=1\),则 \(\mu(x)=1\)

  2. \(x=p{1}p{2}p{3}\dots p{k}\),且\(p{i}\)为互不相同的质数,则有\(\mu(x)=(-1)^k\)

  3. 其他情况中 \(\mu(x)=0\)

    莫比乌斯函数中有用的性质还是挺多的,这里就只列出一个最常用的炒鸡重要的性质

    \(\sum_{d\mid n}\mu(d)=[n=1]\)

这条性质可以运用到很多与\(gcd\)有关的题目中的推导式子中,非常重要

同时,莫比乌斯函数还是一个积性函数
在这里给大家提及一下积性函数\(f\):既当\(gcd(i,j)=1\)时,\(f(xy)=f(x)f(y)\)的函数叫积性函数
积性函数的性质
  1. \(f(1)=1\)
  2. 积性函数的前缀和也是积性函数

莫比乌斯函数就是借助了它是积性函数的特点,使其可以通过线性筛得到

求莫比乌斯函数\(\mu\)的代码
inline void init()
{
    mu[1]=1;
    for(int i=2;i<N;i++)
    {
        if(!vis[i])
        {
            prime[++cnt]=i;
            mu[i]=-1;
        }
        for(int j=1;j<=cnt&&i*prime[j]<N;j++)
        {
            vis[i*prime[j]]=1;
            if(i%prime[j]==0)break;
            mu[i*prime[j]]=-mu[i];
        }
    }
}

莫比乌斯反演和函数可以运用在很多题目的公式推导上,重点还是公式的推导


三、整除分块

整除分块是在莫比乌斯反演题中重要的一环,将询问的复杂度的从\(O(n)\)优化成\(O(\sqrt n)\),可以成功解决大多数数据较大的题目,十分重要
整除分块用于求\(\sum_{i=1}^n\left \lfloor \frac{n}{i} \right \rfloor\)的普遍情况(并不强制如上形式)下,只要满足有规律的一段区间中的值是相同的,就可以用整除分块。我们来看看对于较简单的整除分块。

若令\(n=22,x=\left \lfloor \frac{n}{i} \right \rfloor\),则有:

\(i=1\)时,\(x=22\)

\(i=2\)时,\(x=11\)

\(i=3\)时,\(x=7\)

\(i=4\)时,\(x=5\)

\(i=5\)时,\(x=4\)

\(i=6\)时,\(x=3\)

\(i=7\)时,\(x=3\)

\(i=8\)时,\(x=2\)

\(i=9\)时,\(x=2\)

\(i=10\)时,\(x=2\)

\(i=11\)时,\(x=2\)

\(i=12\)时,\(x=1\)

\(i=13\)时,\(x=1\)

\(\vdots\)

\(i=22\)时,\(x=1\)

由上可以看到,由几段区间的\(x\)是相同的,我们可以通过\(l=(上一次的r) +1,r=n/(n/l)\)得到区间\([l,r]\),可以\(O(1)\)时间算出这段区间的\(x\)的和,最后起到求和的作用
void solve()
{
    int ans=0;
    for(int l=1,r;l<=n;l=r+1)
    {
        r=n/(n/l);
        ans+=(r-l+1)*(n/(n/l));
    }
}

转载于:https://www.cnblogs.com/ShuraEye/p/11354750.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值