讲道理莫比乌斯反演也算组合数学,不过因为听起来很高大上所以新开了一篇。


抄袭来源

https://www.cnblogs.com/peng-ym/p/8647856.html

https://www.cnblogs.com/peng-ym/p/9446555.html

https://www.luogu.org/blog/An-Amazing-Blog/mu-bi-wu-si-fan-yan-ji-ge-ji-miao-di-dong-xi

https://www.cnblogs.com/asuldb/p/10205579.html


#define

$[A]$:若事件$A$成立为$1$,反之为$0$。

$\dfrac{n}{i}$:默认向下取整。有的懒得打向下取整号了

凡出现$n$和$m$,默认$n<m$。


整除分块

在$O(\sqrt{n})$时间内求出$\sum\limits_{i=1}^n\left\lfloor\dfrac{n}{i}\right\rfloor$。

显然$\left\lfloor\dfrac{n}{i}\right\rfloor$只有$O(\sqrt{n})$种取值。

然后有个性质就是对于$\forall i\in[l,(n/(n/l))]$,都有$\left\lfloor\dfrac{n}{i}\right\rfloor=\left\lfloor\dfrac{n}{l}\right\rfloor$。

这样就能把$n$分成$\sqrt{n}$段,每段统一求和。

int sum(int n){
    int ans=0;
    for(register int l=1,r;l<=n;l=r+1){
        r=n/(n/l);
        ans+=(r-l+1)*(n/l);
    }
    return ans;
}

同理也能做到$O(\sqrt{n})$求$\sum\limits_{i=1}^n\left\lfloor\dfrac{n}{i}\right\rfloor\left\lfloor\dfrac{m}{i}\right\rfloor$,也能把r-l+1换成别的,甚至可以用于求$\sum\limits_{i=1}^nf(\lfloor\dfrac{n}{i}\rfloor,\lfloor\dfrac{m}{i}\rfloor)$。

证明的话「算法竞赛·进阶指南」关于「余数求和」一题的解法写的就很好。


莫比乌斯函数

定义

定义$\mu(n)$为莫比乌斯函数。

根据算数基本定理将$n$分解:$n=\prod\limits_{i=1}^kp_i^{c_i}$

如果$\exists c_i>1$,则$\mu(n)=0$。

否则$\mu(n)=(-1)^k$。

特别的,$\mu(1)=1$。

性质

1.$\mu(n)$为积性函数

于是就能线筛它:

int prime[maxn],mu[maxn],cnt,n;
bool is[maxn];
void sieve(){
    mu[1]=is[1]=1;
    for(register int i=2;i<=n;++i){
        if(!is[i])prime[++cnt]=i,mu[i]=-1;
        for(register int j=1;j<=cnt&&i*prime[j]<=n;++j){
            is[i*prime[j]]=1;
            if(i%prime[j]==0){mu[i*prime[j]]=0;break;}
            mu[i*prime[j]]=-mu[i];
        }
    }
}

2.$\sum\limits_{d|n}\mu(d)=[n=1]$

肥肠重要的性质。

证明:

$n=1$时为$1$。

$n>1$时,将$n$分解为$\prod\limits_{i=1}^kp_i^{c_i}$。

考虑它每个约数的贡献,若$c_i>1$则贡献为零,我们只考虑$c_i\le 1$的情况,也就相当于选出若干个$p_i$。

选$i$个$p_i$有$C_k^i$种情况,贡献和为:

$\sum\limits_{i=0}^kC_k^i(-1)^i$

后面乘上个$1^{k-i}$:

$=\sum\limits_{i=0}^kC_k^i(-1)^i1^{k-i}$

这不二项式定理吗?

$=(-1+1)^k$

$=0$

3.$\sum\limits_{d|n}\dfrac{\mu(d)}{d}=\dfrac{\varphi(n)}{n}$

狄雷克雷卷积中会证明。


狄雷克雷卷积

杜教筛里会用到,这里也用来证明莫比乌斯反演。

常见积性函数

欧拉函数$\varphi(n)$,约数个数函数$d(n)$,约数和函数$\sigma(n)$,莫比乌斯函数$\mu(n)$

下面是一些刚见到的完全积性函数:

  • 元函数$e(n)=[n=1]$
  • 常函数$1(n)=1$
  • 单位函数$id(n)=n$
  • 幂函数$id^k(n)=n^k$

定义

卷积的符号为$*$。

对于函数$f(n)$和$g(n)$,定义:

$(f*g)(n)=\sum\limits_{d|n}f(d)g(\dfrac{n}{d})$

写的时候可以把$(n)$省略掉。

性质

1.交换律

$f*g=g*f$

2.结合律

$(f*g)*h=f*(g*h)$

3.分配律

$(f+g)*h=f*h+g*h$

4.积性函数卷积性函数还是积性函数

5.$e(n)$就是卷积里的单位元,即$f*e=f$

下面$2$条是由$\mu,\varphi$自身的性质得来的:

6.$\mu*1=e$

7.$\varphi*1=id$

我们来用这$2$条性质证明$\sum\limits_{d|n}\dfrac{\mu(d)}{d}=\dfrac{\varphi(n)}{n}$:

给$\mu$卷个$id$:

$\mu*id=\mu*\varphi*1$

$\mu*id=\varphi*e$

$\sum\limits_{d|n}\mu(d)\dfrac{n}{d}=\varphi(n)$

$\sum\limits_{d|n}\dfrac{\mu(d)}{d}=\dfrac{\varphi(n)}{n}$


莫比乌斯反演

式子

就是这个:

$f(n)=\sum\limits_{d|n}g(d)\leftrightarrow g(n)=\sum\limits_{d|n}\mu(d)f(\dfrac{n}{d})$

还有一种形式:

$f(d)=\sum\limits_{d|n}g(n)\leftrightarrow g(d)=\sum\limits_{d|n}\mu(\dfrac{n}{d})f(n)$

证明

$f(n)=\sum\limits_{d|n}g(d)$

可以看做$f=g*1$

两边都卷个$\mu$:

$f*\mu=g*1*\mu$

前面写过$\mu*1=e,f*e=f$

则$f*\mu=g$

即$g(n)=\sum\limits_{d|n}f(d)\mu(\dfrac{n}{d})$

栗子

莫比乌斯反演能干啥?

举个栗子:求$\sum\limits_{i=1}^n\sum\limits_{j=1}^m[gcd(i,j)=k]$

正规做法

设$f(d)=\sum\limits_{i=1}^n\sum\limits_{j=1}^m[gcd(i,j)=d],g(d)=\sum\limits_{d|n}f(n)$

可以发现$g(d)$就是在枚举$d|gcd(i,j)$的倍数的情况,即前$n$个数中能被$d$整除的数的个数和前$m$个数中能被$d$整除的数的个数。

则$g(d)=\left\lfloor\dfrac{n}{d}\right\rfloor\left\lfloor\dfrac{m}{d}\right\rfloor$。

显然可以莫比乌斯反演,$f(i)=\sum\limits_{i|d}\mu(\dfrac{d}{i})g(d)=\sum\limits_{i|d}\mu(\dfrac{d}{i})\left\lfloor\dfrac{n}{d}\right\rfloor\left\lfloor\dfrac{m}{d}\right\rfloor$。

答案为$f(k)=\sum\limits_{k|d}\mu(\dfrac{d}{k})\left\lfloor\dfrac{n}{d}\right\rfloor\left\lfloor\dfrac{m}{d}\right\rfloor$,枚举$k$的倍数,上界显然为$\left\lfloor\dfrac{n}{k}\right\rfloor$:

$f(k)=\sum\limits_{i=1}^{\lfloor\frac{n}{k}\rfloor}\mu(i)\left\lfloor\dfrac{n}{ik}\right\rfloor\left\lfloor\dfrac{m}{ik}\right\rfloor$

把$n,m$都除以$k$,预处理$\mu$的前缀和,后面这一坨就能整除分块$O(\sqrt{n})$做了。

常见做法

真的做反演题的时候用得最多的还是$\sum\limits_{d|n}\mu(d)=[n=1]$。

还是这道题,枚举$k$的倍数:

$\sum\limits_{i=1}^n\sum\limits_{j=1}^m[gcd(i,j)=k]$

$=\sum\limits_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{k}\rfloor}[gcd(i,j)=1]$

直接把$\mu$的性质往上套:

$=\sum\limits_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{k}\rfloor}\sum\limits_{d|gcd(i,j)}\mu(d)$

$d|gcd(i,j)$和$d|i,d|j$是等价的,然后我们改为枚举$d$,上界为$\left\lfloor\dfrac{n}{k}\right\rfloor$,再变换一下求和顺序:

$=\sum\limits_{d=1}^{\lfloor\frac{n}{k}\rfloor}\sum\limits_{i=1}^{\lfloor\frac{n}{k}\rfloor}[d|i]\sum\limits_{j=1}^{\lfloor\frac{m}{k}\rfloor}[d|j]\mu(d)$

显然,$\sum\limits_{i=1}^n[d|i]=\left\lfloor\dfrac{n}{d}\right\rfloor$:

$=\sum\limits_{d=1}^{\lfloor\frac{n}{k}\rfloor}\mu(d)\left\lfloor\dfrac{n}{dk}\right\rfloor\left\lfloor\dfrac{m}{dk}\right\rfloor$


杜教筛

做反演题的时候有些是需要杜教筛的,然后就被送过来学了。

杜教筛可以在$O(n^{\frac{2}{3}})$求出某些数论函数的单项前缀和。

推导

假设我们有函数$f$,前缀和记为$S$,求$S(n)$。

设出另外两个函数$g,h$,满足$h=f*g$。

即$h=\sum\limits_{d|n}g(d)f(\dfrac{n}{d})$

对$h$做个前缀和:

$\sum\limits_{i=1}^nh(i)=\sum\limits_{i=1}^n\sum\limits_{d|i}g(d)f(\dfrac{i}{d})$

我们发现等号后面两个$\sum$就是把$1\sim n$的约数枚举了一遍。

于是改为枚举$d$:

$\sum\limits_{i=1}^nh(i)=\sum\limits_{d=1}^ng(d)\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}f(\dfrac{id}{d})=\sum\limits_{d=1}^ng(d)S(\dfrac{n}{d})$

把$d=1$提出来:

$\sum\limits_{i=1}^nh(i)=g(1)S(n)+\sum\limits_{d=2}^ng(d)S(\dfrac{n}{d})$

移项:

$g(1)S(n)=\sum\limits_{i=1}^nh(i)-\sum\limits_{d=2}^ng(d)S(\dfrac{n}{d})$

$g(1)S(n)=\sum\limits_{i=1}^n(f*g)(i)-\sum\limits_{d=2}^ng(d)S(\dfrac{n}{d})$

如果选取了合适的$g$使$f*g$的前缀和便于计算的话,就能整除分块递归计算$S(\dfrac{n}{d})$了。

应用

莫比乌斯函数

我们知道$\mu* 1=e$,显然$e$的前缀和就是$1$。

把$g$配为$1$,就有$S(n)=1-\sum\limits_{d=2}^nS(\dfrac{n}{d})$

欧拉函数

欧拉函数有$\varphi*1=id$,$id$前缀和就是自然数前$n$项和。

于是$S(n)=\sum\limits_{i=1}^ni-\sum\limits_{d=2}^nS(\dfrac{n}{d})$

奇怪的欧拉函数

求$\sum\limits_{i=1}^ni\varphi(i)$。

要消去烦人的$i$,给$i\varphi(i)$卷上$id$:

$i\varphi(i)*id=\sum\limits_{d|n}d\varphi(d)\dfrac{n}{d}=n\sum\limits_{d|n}\varphi(d)=n^2$

$S(n)=\sum\limits_{i=1}^ni^2-\sum\limits_{d=2}^ndS(\dfrac{n}{d})$

实现

一般是先线筛出部分前缀和,再配合上记忆化。

以$\mu$为例:

#define maxn 10000001
#define inf 0x3f3f3f3f
const int Mod = 1e6 + 7;
struct hash{
    int h[Mod],d[Mod],s[Mod],nex[Mod],cnt;
    void insert(int x,int y){
        s[++cnt]=x,x%=Mod,nex[cnt]=h[x],d[h[x]=cnt]=y;
    }
    int find(int x){
        for(register int i=h[x%Mod];i;i=nex[i])
            if(s[i]==x)return d[i];
        return -inf;
    }
}mmu;//哈希记忆化
int mu[maxn],prime[maxn>>2],cnt;
bool is[maxn];
void sieve(){
    is[1]=mu[1]=1;
    for(register int i=2;i<maxn;++i){
        if(!is[i])prime[++cnt]=i,mu[i]=-1;
        for(register int j=1;j<=cnt&&i*prime[j]<maxn;++j){
            is[i*prime[j]]=1;
            if(i%prime[j]==0){mu[i*prime[j]]=0;break;}
            mu[i*prime[j]]=-mu[i];
        }
    }
    for(register int i=2;i<maxn;++i)mu[i]+=mu[i-1];
}//筛出前maxn的前缀和
int smu(int n){
    if(n<maxn)return mu[n];
    int ans=mmu.find(n);
    if(ans!=-inf)return ans;
    ans=1;
    for(register int l=2,r;l<=n;l=r+1){
        r=n/(n/l);
        ans-=(r-l+1)*smu(n/l);
    }
    mmu.insert(n,ans);
    return ans;
}

vim没有c++11开不了unordered_map只好手写哈希

还有种更高端的记忆化。

由于求的前缀和都是$N$的约数,开一个$\sqrt{N}$大小的数组$mmu$。

若$n\le \sqrt{n}$返回$mmu[n]$,否则返回$mmu[\sqrt{N}+N/n]$。

然而每次都要清空$mmu$数组。

复杂度

不提前线筛的话复杂度是$O(n^{\frac{3}{4}})$

如果线筛出前$n^{\frac{2}{3}}$的前缀和的话是$O(n^{\frac{2}{3}})$

不会证(理直气壮)

还有个很有意思的东西:

整除分块套杜教筛:

    for(register int l=1,r;l<=n;l=r+1){
        r=n/(n/l);
        ans+=(smu(r)-smu(l-1))*(n/l);
    }

上面这个的复杂度是$O(\sqrt{n}+n^{\frac{2}{3}})$的!

由于每个块的右端点都是$n/(n/l)$,而$l-1$相当于上一个块的右端点,我们可以看做取遍了$\left\lfloor\dfrac{n}{i}\right\rfloor$。而在杜教筛中求$S(n)$的时候已经把$S(\left\lfloor\dfrac{n}{i}\right\rfloor)$都算过了,所以记忆化之后这些值都可以$O(1)$得到,整个复杂度就是加起来的。

同理,杜教筛套杜教筛的复杂度为$O(n^{\frac{2}{3}})$。


水题

Problem b

其实是个容斥,也算是二维前缀和。

设$f(n,m)=\sum\limits_{i=1}^n\sum\limits_{j=1}^m[gcd(i,j)=k]$

求$\sum\limits_{i=a}^b\sum\limits_{j=c}^{d}[gcd(i,j)=k]$

我们暴力展开或者把它想象成二维平面上的一个矩形,就变成了$f(b,d)-f(b,c-1)-f(a-1,d)+f(a-1,c-1)$

然后就是栗子了。

YY的GCD

求$\sum\limits_{i=1}^n\sum\limits_{j=1}^m[gcd(i,j)\in prime]$

暴力枚举质数:

$=\sum\limits_{a\in prime}\sum\limits_{i=1}^n\sum\limits_{j=1}^m[gcd(i,j)=a]$

套路地变换:

$=\sum\limits_{a\in prime}\sum\limits_{i=1}^{\lfloor\frac{n}{a}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{a}\rfloor}\sum\limits_{d|gcd(i,j)}\mu(d)$

$=\sum\limits_{a\in prime}\sum\limits_{d=1}^{\lfloor\frac{n}{a}\rfloor}\left\lfloor\dfrac{n}{ad}\right\rfloor\left\lfloor\dfrac{m}{ad}\right\rfloor\mu(d)$

这样复杂度还是太高。

设$k=ad$,显然$a|k$。改为枚举$k$:

$=\sum\limits_{a\in prime}\sum\limits_{k=1}^n[a|k]\left\lfloor\dfrac{n}{k}\right\rfloor\left\lfloor\dfrac{m}{k}\right\rfloor\mu(d)$

变换求和顺序:

$=\sum\limits_{k=1}^n\left\lfloor\dfrac{n}{k}\right\rfloor\left\lfloor\dfrac{m}{k}\right\rfloor\sum\limits_{a\in prime}[a|k]\mu(d)$

这样前面的可以整除分块,后面那一坨可以预处理。对于每个质数,给它的倍数加上$\mu$即可。

约数个数和

题解

Crash的数字表格

题解

选数

这个题直接把我送去学杜教筛了。

个人习惯把$H$看作$R$,把$N$看作$n$。

求$\sum\limits_{i_1=L}^R\sum\limits_{i_2=L}^R···\sum\limits_{i_n=L}^R[gcd(i_1,i_2,…i_n)=k]$

如果玩套路的话感觉有点麻烦,试试正规反演:

先转化一下,枚举$k$的倍数,这样$R=\lfloor\dfrac{R}{k}\rfloor,L=\lceil\dfrac{L}{k}\rceil$

就成了$\sum\limits_{i_1=L}^R\sum\limits_{i_2=L}^R···\sum\limits_{i_n=L}^R[gcd(i_1,i_2,…i_n)=1]$

设$f(d)=\sum\limits_{i_1=L}^R\sum\limits_{i_2=L}^R···\sum\limits_{i_n=L}^R[gcd(i_1,i_2,…i_n)=d],g(d)=\sum\limits_{d|n}f(n)$

考虑$g$的含义,就是有$n$个值域为$[L,R]$的数,它们的$gcd$为$d$的倍数。

$g(d)=\left(\left\lfloor\dfrac{R}{d}\right\rfloor-\left\lfloor\dfrac{L-1}{d}\right\rfloor\right)^{n}$

反演得:$f(d)=\sum\limits_{d|n}\mu(n)g(\dfrac{n}{d})$

答案为$f(1)=\sum\limits_{i=1}^R\mu(i)g(i)$

后面$g$可以整除分块,$R$达到$1e9$要杜教筛。复杂度为$O(n^{\frac{2}{3}}+\sqrt{n}\log n)$。

于神之怒加强版

上面那道题送我去学了杜教筛,这道题送我去重学了遍线筛。

推法很套路,最后求的是$\sum\limits_{T=1}^n\left\lfloor\dfrac{n}{T}\right\rfloor\left\lfloor\dfrac{m}{T}\right\rfloor\sum\limits_{d|T}d^k\mu(\dfrac{T}{d})$

然后就是筛$f(T)=\sum\limits_{d|T}d^k\mu(\dfrac{T}{d})$。$n$有$5e6$,简单的$O(n\log n)$筛法不好过了。

显然$f=\mu*id^k$是个积性函数,可以考虑线筛。

对于质数$p$:

$f(p)=p^k-1$

$f(p^m)=(p^m)^k-(p^{m-1})^k$

我们要推到$f(p^{m+1})=(p^m)^k-(p^{m-1})^k=(p^k-1)(p^k)^m=f(p)(p^k)^m$

对于所有仅有一个质因子的数维护函数$g(p^m)=(p^k)^m$,这个是可以推上去的。

则$f(p^{m+1})=f(p)g(p^m)$。

考虑到我们仅对每个质数做快速幂,复杂度还是$O(\dfrac{n}{\ln n}\log k)=O(n)$的。

线筛代码:

#define maxn 5000001
const int mod = 1000000007;
int g[maxn],f[maxn],low[maxn],prime[maxn>>2],cnt;
bool is[maxn];
void sieve(){
    f[1]=is[1]=1;
    for(register int i=2;i<maxn;++i){
        if(!is[i])prime[++cnt]=i,f[i]=quickpow(i,k)-1,g[i]=f[i]+1,low[i]=i;
        for(register int j=1;j<=cnt&&i*prime[j]<maxn;++j){
            is[i*prime[j]]=1;
            if(i%prime[j]==0){
                low[i*prime[j]]=low[i]*prime[j];
                if(low[i]==i)g[i*prime[j]]=1ll*g[i]*g[prime[j]]%mod,f[i*prime[j]]=1ll*g[i]*f[prime[j]]%mod;
                else f[i*prime[j]]=1ll*f[i/low[i]]*f[low[i]*prime[j]]%mod;
                break;
            }
            low[i*prime[j]]=prime[j];
            f[i*prime[j]]=1ll*f[i]*f[prime[j]]%mod;
        }
    }
}

简单的数学题

题解

数表

求$\sum\limits_{i=1}^n\sum\limits_{j=1}^m\sigma(gcd(i,j))[\sigma(gcd(i,j))\le a]$

套路推完式子长这样:$\sum\limits_{T=1}^n\left\lfloor\dfrac{n}{i}\right\rfloor\left\lfloor\dfrac{m}{i}\right\rfloor\sum\limits_{d|T,\sigma(d)\le a}\mu(\dfrac{T}{d})\sigma(d)$

所有数按$\sigma$排序,把询问离线下来按$a$排序。

处理每个询问前依次把$\sigma(i)\le a$的数的贡献算上。

这样就是若干个单点加和区间查,树状数组维护即可。

模数是$2^{31}$可以自然溢出$int$。

复杂度$O(n\log^2n+T\sqrt{n}\log n)$

数字表格

题解