Mobius反演方法

本文介绍了Mobius反演和Dirichlet卷积的概念,包括欧拉筛法、Dirichlet卷积的性质及其在数论函数中的应用。通过例题展示了反演原理在解决数学问题中的作用,如BZOJ2301和BZOJ2820,强调了反演在实际问题中的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<更新提示>

前置知识:建议有一点 D i r i c h l e t Dirichlet Dirichlet卷积的基础,会线性筛求积性函数。本文可能会持续更新。

可以看我以前在博客园的博客


<正文>

0. 符号及约定

1. 1. 1. [ P ] [P] [P]是指正则表达式,当 P P P t r u e true true时, [ P ] = 1 [P]=1 [P]=1,当 P P P f a l s e false false时, [ P ] = 0 [P]=0 [P]=0

2. 2. 2. 约数个数函数定义为 τ ( n ) = ∑ d ∣ n 1 \tau(n)=\sum_{d|n}1 τ(n)=dn1

3. 3. 3. 约数和函数定义为 σ ( n ) = ∑ d ∣ n d \sigma(n)=\sum_{d|n}d σ(n)=dnd

4. 4. 4. 元函数定义为 e ( n ) = [ n = 1 ] e(n)=[n=1] e(n)=[n=1]

5. 5. 5. 恒等函数定义为 I ( n ) = 1 I(n)=1 I(n)=1

6. 6. 6. 单位函数定义为 ϵ k ( n ) = n k \epsilon_k(n)=n^k ϵk(n)=nk

7. 7. 7. 欧拉函数定义为 φ ( n ) = ∑ i = 1 n [ gcd ⁡ ( i , n ) = 1 ] \varphi(n)=\sum_{i=1}^n[\gcd(i,n)=1] φ(n)=i=1n[gcd(i,n)=1]

8. 8. 8. n = ∏ p i c i n=\prod p_i^{c_i} n=pici,则莫比乌斯函数定义为 μ ( n ) = { 1 n = 1 ( − 1 ) k ∀ c i = 1 0 ∃ c i > 1 \mu(n)=\begin{cases}1&n=1\\(-1)^k& \forall c_i=1\\0&\exist c_i>1\end{cases} μ(n)=1(1)k0n=1ci=1ci>1

9. 9. 9. 对于数论函数 f f f,若满足 gcd ⁡ ( a , b ) = 1 \gcd(a,b)=1 gcd(a,b)=1时,有 f ( a b ) = f ( a ) f ( b ) f(ab)=f(a)f(b) f(ab)=f(a)f(b),则称函数 f f f积性函数

10. 10. 10. 对于两个函数 f , g f,g f,g,定义他们的 d i r i c h l e t dirichlet dirichlet卷积为: ( f × g ) ( n ) = ∑ d ∣ n f ( d ) g ( n d ) (f\times g)(n)=\sum_{d|n}f(d)g(\frac{n}{d}) (f×g)(n)=dnf(d)g(dn)函数 f , g f,g f,g不必要是积性函数

1. 欧拉筛法

前置知识里已经提到过,以下给出本文可能会使用的线性筛代码:

int flag[N],Prime[N],cnt;
inline void EularSieve(void)
{
   
    for (int i=2;i<=Lim;i++)
    {
   
        if ( !flag[i] ) Prime[++cnt] = i;
        for (int j=1;j<=cnt&&i*Prime[j]<=Lim;j++)
        {
   
            flag[ i*Prime[j] ] = true;
            if ( i % Prime[j] == 0 ) break;
        }
    }
}

这是最朴素的欧拉筛法,不过当我们要筛一些比较复杂的积性函数的时候,线性筛方程的推导可能会非常复杂。

因此我们考虑引入一种更好的线性筛法,目的是能够方便的筛出积性函数的值。

首先,我们注意到积性函数的性质:当 gcd ⁡ ( a , b ) = 1 \gcd(a,b)=1 gcd(a,b)=1时,有 f ( a b ) = f ( a ) f ( b ) f(ab)=f(a)f(b) f(ab)=f(a)f(b)。那么对于一个任意的正整数 n n n,我们可以用算术基本定理进行分解:

n = ∏ i = 1 k p i c i n=\prod_{i=1}^kp_i^{c_i} n=i=1kpici

此时,任意的 i , j ∈ [ 1 , k ] i,j\in[1,k] i,j[1,k]都满足 gcd ⁡ ( p i c i , p j c j ) = 1 \gcd(p_i^{c_i},p_j^{c_j})=1 gcd(pici,pjcj)=1。那么我们就可以得到:

f ( n ) = f ( ∏ i = 1 k p i c i ) = ∏ i = 1 k f ( p i c i ) f(n)=f\left(\prod_{i=1}^kp_i^{c_i}\right)=\prod_{i=1}^kf(p_i^{c_i}) f(n)=f(i=1kpici)=i=1kf(pici)

那么我们就有一个想法:利用定义求出积性函数 f f f在所有素数幂出的取值,然后直接递推出所有函数值

具体地说,可以这样递推:

f[1] = 1;
for (int i=2;i<=Lim;i++)
    if ( i == Pow[i] ) f[i] = calc(p[i],e[i]);
    else f[i] = f[i/Pow[i]] * f[Pow[i]];

其中 p [ i ] p[i] p[i]代表数 i i i的最小素因子, e [ i ] e[i] e[i]代表 i i i的分解式中 p [ i ] p[i] p[i]这个素因子的指数, c a l c calc calc就是求素数幂处取值的函数,而 P o w [ i ] = p [ i ] e [ i ] Pow[i]=p[i]^{e[i]} Pow[i]=p[i]e[i],,这样是不是就符合我们的要求了呢?

那么现在我们的问题就是如何求出 p , e , P o w p,e,Pow p,e,Pow这三个数组,幸运的是,他们都可以在线性筛的过程中求。

根据欧拉筛法每次用一个数的最小素因子筛去这个合数,就可以更新这三个数组的值了。

代码如下:

int p[N],e[N],Pow[N],Prime[N],cnt;
inline void EularSieve(void)
{
   
    Pow[1] = p[1] = 1 , e[1] = 0;
    for (int i=2;i<=Lim;i++)
    {
   
        if ( p[i] == 0 )
            p[i] = Pow[i] = Prime[++cnt] = i , e[i] = 1;
        // 判定一个新素数
        for (int j=1;j<=cnt&&i*Prime[j]<=Lim;j++)
        {
   
            int Next = i * Prime[j];
            if ( p[i] == Prime[j] )
            {
   
                e[Next] = e[i] + 1;
                Pow[Next] = Pow[i] * Prime[j];
                // 有相同的素因子
                break;
            }
            else e[Next] = 1 , Pow[Next] = Prime[j];
            // 没有相同的素因子
        }
    }
    f[1] = 1;
    for (int i=2;i<=Lim;i++)
        if ( i == Pow[i] ) f[i] = calc(p[i],e[i]);
        else f[i] = f[i/Pow[i]] * f[Pow[i]];
}

2. D i r i c h l e t Dirichlet Dirichlet卷积

2.1 D i r i c h l e t Dirichlet Dirichlet卷积的性质

1. 1. 1. 两个积性函数 f f f g g g d i r i c h l e t dirichlet dirichlet卷积仍为积性函数。

证明:

设有两个积性函数 f f f g g g,则它们的 d i r i c h l e t dirichlet dirichlet卷积为:

h = f × g = ∑ d ∣ n f ( d ) g ( n d ) h=f\times g=\sum_{d|n}f(d)g(\frac{n}{d}) h=f×g=dnf(d)g(dn)

对于函数 h h h则可以得到:

h ( x ) h ( y ) = ( ∑ d 1 ∣ x f ( d 1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值