各类反演与狄利克雷卷积


听起来很 nb,很有名但比较难学的一个算法类型。然而确实很 nb。

我竟然在学 ymx 一年半前就学过的东西。

1. 反演的本质与第一反演公式

1.1. 什么是反演

反演是通过用 \(f\) 表示 \(g\) 的方法求出如何用 \(g\) 表示 \(f\)

如果我们已知 \(g(n)\) 以及它如何用 \(f\) 表示:\(g(n)=\sum_{i=1}^nc_{n,i}f(i)\),从而反推出用 \(g\) 表示 \(f\) 的方法:\(f(n)=\sum_{i=1}^nd_{n,i}g(i)\),那么就算 \(f\) 无法直接求,也可以通过 \(g(i)\) 的值推出 \(f(n)\)

上面二式互为反演公式。

1.2. 第一反演公式

这里直接给出定理:如果 \(n\) 次多项式 \(p\)\(q\) 分别满足以下公式:\(p_n(x)=\sum_{i=1}^n c_{n,i}q_i(x)\)\(q_n(x)=\sum_{i=1}^n d_{n,i} p_i(x)\),且 \(c_{j,j}\neq0,d_{j,j}\neq 0\),那么

\[v_n=\sum_{i=1}^n c_{n,i} u_i\Leftrightarrow u_n=\sum_{i=1}^n d_{n,i} v_i \tag{1} \]

简单来说,如果将 \(c,d\) 写成矩阵的形式 \(\mathbf{C},\mathbf{D}\),那么它显然是下三角矩阵,同时有 \(\mathbf{CD}=\mathbf{I}\)。因为如果将 \(p,q\) 写成列向量 \(\mathbf{p},\mathbf{q}\),那么条件中的两个公式可以表示为 \(\mathbf{p}=\mathbf{Cq}\)\(\mathbf{q}=\mathbf{Dp}\),即 \(\mathbf{p}=\mathbf{CDp}\),得证。由于 \(\mathbf{C}\)\(\mathbf{D}\) 互逆,所以它们的行列式不为 \(0\),而因为它们是下三角矩阵,因此一定有对角线元素不为 \(0\),这也就解释了为什么 \(c_{j,j}\neq 0\)\(d_{j,j}\neq 0\)

通俗地讲,只要我们找到任何一组符合条件的 \(p,q\)\(c,d\),就可以将 \(p,q\) 推广至任意 \(n\) 次多项式,因为 \(\mathbf{C}\)\(\mathbf{D}\) 永远是互逆的,不随 \(p,q\) 的改变而改变。这就意味着为了证明某个反演公式成立,我们只需考虑一种方便证明的特殊情况即可

2. 二项式反演

2.1. 引入

在玩二项式定理的时候,如果你尝试把 \(x\) 变成 \(1+(x-1)\),那么可能会有新的收获:

\[x^n=(1+x-1)^n=\sum_{i=0}^n \dbinom{n}{i}1^{n-i}(x-1)^i=\sum_{i=0}^n \dbinom{n}{i}(x-1)^i \]

耶?和反演公式的形式长得很像诶!那么试试能不能用 \(x\) 表示 \(x-1\)

\[(x-1)^n=\sum_{i=0}^n\dbinom{n}{i}(-1)^{n-i}x^i \]

很好!如果令 \(p_i=x^i\)\(q_i=(x-1)^i\)\(c_{i,j}=\dbinom{i}{j}\)\(d_{i,j}=\dbinom{i}{j}(-1)^{i-j}\),那么我们就成功找到了一组 \(p,q,c,d\)

综上,我们有:

\[f_n=\sum_{i=0}^n\dbinom{n}{i}g_i\Leftrightarrow g_n=\sum_{i=0}^n (-1)^{n-i}f_i \tag{2.3} \]

其中 \(f_n\) 表示至多 \(n\)\(g_n\) 表示恰好 \(n\)。这就是二项式反演,上面的引入就是它的证明。

如果将矩阵转置,那么还可以得到另一种表示方法:

\[f_i=\sum_{j=i}^n\dbinom{j}{i}g_j\Leftrightarrow g_i=\sum_{j=i}^n(-1)^{j-i}\dbinom{j}{i}f_j \tag{2.4} \]

其中 \(f_n\) 表示至少 \(n\)\(g_n\) 表示恰好 \(n\)

2.2. 直观理解

实际上二项式反演的本质是容斥原理\(f_i\) 表示至少 / 至多 \(i\)的方案数,而 \(g_i\) 表示恰好 \(i\)的方案数。

一般情况下,使用容斥原理时,如果固定 \(i\),那么任选 \(i\) 个元素的贡献不一定相等。这就意味着我们必须 \(2^n\) 枚举每一种情况。而相反,如果任选 \(i\) 个数时贡献只与 \(i\) 有关而与所选择的数无关,由于固定了 \(i\) 故也即贡献相等,就可以简化为二项式反演。这是使用二项式反演的情况之一,另一种情况见应用部分。

2.3. 应用

在 OI 中,二项式反演的应用通常与动态规划相结合(当然也不乏直观解释中的情况,如下方的三类问题):DP 求出至少 / 至多选择 \(i\) 个元素时的总贡献是简单的,那么我们就可以通过二项式反演,得到恰好选择 \(i\) 个元素时的总贡献。第四节例题部分很好地体现了这一点。

综上,我们总结出二项式定理的核心:进行至少 / 至多和恰好的转换

2.3.1. 错排问题

\(n\) 个人排列,求每个人都恰好站错的方案数。

\(g_n\) 表示 \(n\) 个人的错排方案数,而 \(f_n\) 表示所有排列方案数,即 \(n!\),那么显然有 \(f_n=\sum_{i=0}^n\dbinom{n}{i}g_i\)\(i\) 的意义是站错的人的个数。从而反推出 \(g_n=\sum_{i=0}^n(-1)^{n-i}\dbinom{n}{i}f_i=\sum_{i=0}^n(-1)^{n-i}\dfrac{n!}{(n-i)!}\)(组合数分母上的 \(i!\)\(f_i\) 抵消了)。

2.3.2. 染色问题 I(一维)

\(n\) 个格子,\(k\) 种颜色,相邻格子颜色不同,每个颜色至少出现一次,求方案数。

\(g_k\) 表示恰好出现 \(k\) 个颜色的方案数,\(f_k\) 表示至多出现 \(k\) 个颜色的方案数,即 \(k\times (k-1)^{n-1}\)。显然有 \(f_k=\sum_{i=0}^k \dbinom{k}{i}g_i\),从而反推出 \(g_k=\sum_{i=0}^k(-1)^{k-i}\dbinom{k}{i}f_i\)。显然可以 \(\mathcal{O}(k\log n)\) 计算。

2.3.3. 染色问题 II(二维)

\(n\times m\) 个格子,\(1\) 种颜色,每行和每列至少有一个格子被涂色,求方案数。

\(g_{i,j}\) 表示恰好有 \(i\)\(j\) 列被涂色,\(f_{i,j}\) 表示至多有 \(i\)\(j\) 列被涂色的方案数,即 \(2^{ij}\)。那么对 \(i\)\(j\) 这一维分别二项式反演,有 \(f_{n,m}=\sum_{i=0}^n\dbinom{n}{i}\sum_{j=0}^m \dbinom{m}{j}g_{i,j}\),从而反推出 \(g_{n,m}=\sum_{i=0}^n\sum_{j=0}^m (-1)^{(n-i)+(m-j)}\dbinom{n}{i}\dbinom{m}{j}f_{i,j}\),时间复杂度 \(\mathcal{O}(n^2)\)

2.3.4. 染色问题 III(三维)

\(n\times m\) 个格子,\(k\) 种颜色,每行和每列至少一个格子被染色,每个颜色至少出现一次,格子可不被涂色,求方案数。

请读者结合染色问题 I. 与 II. 自行思考。

2.4. 参考文章

2.5. 例题

*I. P6478 [NOI Online #2 提高组] 游戏

很不错的题目,可以用来入门二项式反演。

\(f_x\) 为钦定 \(x\) 对祖先关系的情况总数(即祖先关系至少有 \(x\) 对),\(g_x\) 为答案,那么根据二项式反演有 \(g_x=\sum_{i=x}^{n}(-1)^{i-x}\dbinom{i}{x}f_i\)

\(f_x\) 可以树形背包求,别忘了最后乘上 \((m-x)!\),因为剩下 \(m-x\) 对点对顺序可以任意。时间复杂度 \(\mathcal{O}(n^2)\)

const int N=5e3+5;

ll n,sz[N],a[N],f[N][N],C[N][N];
char s[N];
vector <int> e[N];
void dfs(int id,int fa){
	f[id][0]=1;
	for(int it:e[id]){
		if(it==fa)continue;
		dfs(it,id),mem(f[0],0,N);
		for(int i=0;i<=sz[id]/2;i++)
			for(int j=0;j<=sz[it]/2;j++)
				f[0][i+j]=(f[0][i+j]+f[id][i]*f[it][j])%mod;
		sz[id]+=sz[it],a[id]+=a[it],cpy(f[id],f[0],N);
	}
	for(int i=min(a[id],sz[id]-a[id])+1;i;i--)
		f[id][i]=(f[id][i]+f[id][i-1]*((s[id]=='1'?a[id]:sz[id]-a[id])-i+1))%mod;
	sz[id]++,a[id]+=s[id]=='0';
}
int main(){
	scanf("%d%s",&n,s+1);
	for(int i=1;i<n;i++){
		int u,v; cin>>u>>v;
		e[u].pb(v),e[v].pb(u);
	} dfs(1,0);
	for(int i=0;i<=n/2;i++)
		for(int j=2;j<=n/2-i;j++)
			f[1][i]=f[1][i]*j%mod;
	for(int i=0;i<=n;i++)
		for(int j=0;j<=i;j++)
			C[i][j]=(j==0||j==i?1:C[i-1][j-1]+C[i-1][j])%mod;
	for(int i=0;i<=n/2;i++){
		ll ans=0;
		for(int j=i;j<=n;j++)
			ans=(ans+((j-i)&1?mod-1:1)*C[j][i]%mod*f[1][j])%mod;
		cout<<ans<<endl;
	}
	
	return 0;
}

*II. P4859 已经没有什么好害怕的了

和上一题极度类似。DP 方法几乎一样,最后也都要乘上阶乘。

实际上,上一题就是把这一题搬到了树上。

ll ksm(ll a,ll b){
	ll s=1;
	while(b){
		if(b&1)s=s*a%mod;
		a=a*a%mod,b>>=1;
	}
	return s;
}
ll inv(ll x){return ksm(x%mod,mod-2);}

ll fc[N],ifc[N];
ll binom(int n,int m){return fc[n]*ifc[m]%mod*ifc[n-m]%mod;}

ll n,k,c,ans;
ll a[N],b[N],f[N];
int main(){
	cin>>n>>k,f[0]=1,c=n+k>>1;
	if((n&1)^(k&1))puts("0"),exit(0);
	for(int i=0;i<=n;i++)fc[i]=i?fc[i-1]*i%mod:1,ifc[i]=inv(fc[i]);
	for(int i=1;i<=n;i++)cin>>a[i]; sort(a+1,a+n+1);
	for(int i=1;i<=n;i++)cin>>b[i];
	for(int i=1;i<=n;i++){
		int cnt=0;
		for(int j=1;j<=n;j++)cnt+=b[j]<a[i];
		for(int j=cnt;j;j--)f[j]=(f[j]+f[j-1]*(cnt-j+1))%mod;
	}
	for(int i=0;i<=n;i++)f[i]=f[i]*fc[n-i]%mod;
	for(int i=c;i<=n;i++)ans=(ans+(i-c&1?mod-1:1)*binom(i,c)%mod*f[i])%mod;
	cout<<ans<<endl;
	return 0;
}

*III. CF1228E Another Filling the Grid

以前不会做,现在也不会。

\(g_{i,j}\) 表示恰好有 \(i\)\(j\) 列的最小值为 \(1\)\(f_{i,j}\) 表示最多有 \(i\)\(j\) 列的最小值为 \(1\),即 \((k-1)^{(n-i)(n-j)}\times k^{n^2-(n-i)(n-j)}\),那么有 \(f_{n,n}=\sum_{i=0}^n\sum_{j=0}^n\dbinom{n}{i}\dbinom{n}{j}g_{i,j}\),二项式反演得到 \(g_{n,n}=\sum_{i=0}^n\sum_{j=0}^n(-1)^{n-i+n-j}\dbinom{n}{i}\dbinom{n}{j}f_{i,j}\)。可以 \(\mathcal{O}(n^2\log k)\) 计算,时间复杂度足够优秀。当然,细节实现可以做到平方甚至线性对数。

l ksm(ll a,ll b){
	ll s=1;
	while(b){
		if(b&1)s=s*a%mod;
		a=a*a%mod,b>>=1;
	}
	return s;
}
ll inv(ll x){return ksm(x%mod,mod-2);}

ll fc[N],ifc[N];
ll binom(int n,int m){return fc[n]*ifc[m]%mod*ifc[n-m]%mod;}

ll n,k,ans;
int main(){
	cin>>n>>k;
	for(int i=0;i<=n;i++)fc[i]=i?fc[i-1]*i%mod:1,ifc[i]=inv(fc[i]);
	for(int i=0;i<=n;i++)
		for(int j=0;j<=n;j++){
			ll c=(n-i)*(n-j);
			ll b=binom(n,i)*binom(n,j)%mod;
			ans=(ans+(n-i+n-j&1?mod-1:1)*b%mod*ksm(k,c)%mod*ksm(k-1,n*n-c))%mod;
		}
	cout<<ans<<endl;
	return 0;
}

3. 单位根反演

3.1. 公式

\[[n\mid x]=\dfrac{1}{n}\sum_{i=0}^{n-1}\omega_n^{xi} \tag{3.1} \]

常规证法是用等比数列求和公式,我不喜欢,因为这样不能使初学单位根反演的同学感受到它的优美与自然,从而让他们感觉单位根反演是一拍脑袋想出来的,就很 artificial。

一个比较直观的,我自己的理解就是 \(\omega_n^x\)\(n\mid x\) 时等于 \(1\)\(n\) 个求和后再除以 \(n\) 就是 \(1\);而在 \(n\nmid x\) 时不妨设 \(d=\gcd(x,n)\)。把单位根放到平面直角坐标系里感受一下,\(\sum_{i=0}^{n-1}(\omega_n^x)^i\) 就是把 \(\omega_n^x\) 旋转 \(n\) 次,每次旋转相同的 \(\dfrac{2\pi x}{n}\) 角度。那么最终形成了相同的 \(d\) 组 “向量”,每组内部有 \(\dfrac{n}{d}\) 个在单位圆上均匀分布的 “向量”,根据高中知识可知每一组向量的和都是 \(0\)

它还有另外一种形式,在做题时经常会遇到

\[[x\equiv y\pmod n]=[x-y\equiv 0\pmod n]=\dfrac{1}{n}\sum_{i=0}^{n-1}\omega_n^{(x-y)i} \tag{3.2} \]

3.2. 应用

我们为什么要用单位根反演?钻研这个问题,不仅可以帮助我们深入理解单位根反演,在做题时我们也能更容易看出它的蛛丝马迹。

3.2.1. 将 mod 转化为求和

首先看一道经典的单位根反演入门题:给出 \(n,s,a_0,a_1,a_2,a_3\leq 10^{18}\),求 \(\sum_{i=0}^n\dbinom{n}{i}s^ia_{i\bmod 4}\)\(998244353\) 取模。

看到组合数和幂结合,自然想到二项式定理,可是 \(a_{i\bmod 4}\) 的部分断绝了我们的出路 …… 吗?Nope.

如果我们将 \(a_{i\bmod 4}\) 写作 \(\sum_{j=0}^3a_j[i\equiv j\pmod 4]\),再使用单位根反演得到 \(\sum_{j=0}^3a_j\times \dfrac{1}{4}\sum_{k=0}^3\omega_4^{(i-j)k}\),揉进原来的柿子:

\[\dfrac{1}{4}\sum_{i=0}^n\dbinom{n}{i}s^i\sum_{j=0}^3a_j\sum_{k=0}^3\omega_4^{(i-j)k} \]

交换求和符号并整理,得

\[\dfrac 1 4\sum_{j=0}^3a_j\sum_{k=0}^3\omega_4^{-jk}\sum_{i=0}^n\dbinom{n}{i}(s\omega_4^k)^i\times 1^{n-i} \]

逆用二项式定理,得

\[\dfrac14\sum_{j=0}^3a_j\sum_{k=0}^3\omega_4^{-jk}(s\omega_4^k+1)^n \]

如果你学过 NTT 就知道在模 \(998244353\) 意义下,原根和单位根可以互换,因此这里的四次单位根就等于 \(g^{\frac{p-1}4}\),一个快速幂解决。时间复杂度 \(\mathcal{O}(\log n)\),有 \(16\) 倍常数。

代码见例题 I.

3.3. 例题

*I. LOJ#6485. LJJ 学二项式定理

ll ksm(ll a,ll b){
	ll s=1;
	while(b){
		if(b&1)s=s*a%mod;
		a=a*a%mod,b>>=1;
	}
	return s;
}

ll T,n,s,a[4],w[4];
int main(){
	cin>>T,w[0]=1,w[1]=ksm(3,mod-1>>2),w[2]=w[1]*w[1]%mod,w[3]=w[1]*w[2]%mod;
	while(T--){
		cin>>n>>s;
		for(int i=0;i<4;i++)cin>>a[i];
		ll ans=0;
		for(int i=0;i<4;i++)
			for(int j=0;j<4;j++){
				ll base=a[i]*w[(16-i*j)%4]%mod;
				ans=(ans+base*ksm((s*w[j])%mod+1,n))%mod;
			}
		cout<<ans*ksm(4,mod-2)%mod<<endl;
	}
	return 0;
}

*II. P5591 小猪佩奇学数学

推推柿子:根据 \(\left\lfloor\dfrac{i}k\right\rfloor=\dfrac{i-i\bmod k}k\),得

\[\dfrac{1}{k}\sum_{i=0}^n\dbinom n i\times p^i\times (i-i\bmod k) \]

略去 \(\dfrac 1 k\),括号拆开分别考虑。

  • 前半部分:\(\sum_{i=0}^n\dbinom n i p^i\times i\)

    根据 \(\dbinom{n}{m}=\dfrac n m\dbinom {n-1}{m-1}\),得 \(np\sum_{i=0}^n\dbinom {n-1}{i-1} p^ {i-1}\)

    \(np(p+1)^{n-1}\)

  • 后半部分:略去负号,得 \(\sum_{i=0}^{n}\dbinom{n}{i}p^i\sum_{j=0}^{k-1}j[i\equiv j\pmod k]\)

    套入单位根反演,得 \(\sum_{i=0}^n\dbinom n ip^i\sum_{j=0}^{k-1}\dfrac j k\sum_{x=0}^{k-1}\omega_k^{(i-j)x}\)

    略去 \(\dfrac 1 k\),交换求和符号,得 \(\sum_{j=0}^{k-1}j\sum_{x=0}^{k-1}\omega_k^{-jx}\sum_{i=0}^n\dbinom ni(p\omega_k^x)^i\)

    套入二项式定理,得 \(\sum_{j=0}^{k-1}j\sum_{x=0}^{k-1}\omega_k^{-jx}(p\omega_k^x+1)^n\)

    然后发现不会了。

    交换求和顺序,得 \(\sum_{x=0}^{k-1}(p\omega_k^x+1)^n\sum_{j=0}^{k-1}j(\omega_k^x)^{-j}\)

    略去前面的柿子,将 \(\omega_k^{-x}\) 记做 \(c\),仅关注 \(\sum_{j=0}^{k-1}jc^{j}\)。由于 \(k\) 是常数,因此将其记做 \(f(c)\)

    看到这里,你发现了什么?对!就是我们小学二年级就学过的错位相减法!

    • 如果 \(c\neq 1\),求 \(cf(c)-f(c)\):比对每一项的系数,有 \(f(c)-cf(c)=\sum_{j=1}^{k-1}c^j-(k-1)c^k\)

      先特判掉 \(k=1\) 的情况,然后用等比数列求和公式得到 \(\sum_{j=1}^{k-1}c^j=-1+\sum_{j=0}^{k-1}c^j=-1+\dfrac{c^k-1}{c-1}\),注意到 \(c^k\) 恒为 \(1\),所以 \(f(c)=\dfrac{-1-(k-1)}{1-c}=\dfrac{k}{c-1}\)

    • 如果 \(c=1\),那么原式等于 \(\sum_{j=0}^{k-1}j=\dfrac{k(k-1)}2\)

    因此直接计算即可!时间复杂度 \(\mathcal{O}(k\log n)\)

ll ksm(ll a,ll b){
	ll s=1; a%=mod;
	while(b){
		if(b&1)s=s*a%mod;
		a=a*a%mod,b>>=1;
	}
	return s;
}
ll inv(ll x){return ksm(x,mod-2);}

ll n,p,k,w,ans,sub;
int main(){
	cin>>n>>p>>k,w=ksm(3,(mod-1)/k);
	ans=n*p%mod*ksm(p+1,n-1)%mod;
	for(int x=0;x<k;x++){
		ll om=ksm(w,x),pw=ksm(p*om+1,n),c=inv(om);
		if(c==1)sub=(sub+pw*(k*(k-1)/2%mod))%mod;
		else sub=(sub+pw*k%mod*inv(mod+c-1))%mod;
	}
	cout<<(ans+mod-sub*inv(k)%mod)*inv(k)%mod;
	return 0;
}

4. 莫比乌斯反演

极其重要的一类反演,对于推式子的帮助很大。

4.1. 前置知识

4.1.1. 数论函数与积性函数

数论函数,就是定义域是正整数的函数。

积性函数,就是对于任意 \(x,y\in \N^{+}\),若 \(\gcd(x,y)=1\),则 \(f(xy)=f(x)f(y)\) 的函数 \(f\)。若完全积性则不需要 \(\gcd(x,y)=1\) 的条件。

一些积性函数举例(接下来的文章中会出现):

  • 单位函数 \(\epsilon(n)=[n=1]\)
  • 常数函数 \(1(n)=1\)
  • 恒等函数 \(\mathrm{id}_k(n)=n^k\)\(\mathrm{id}_1(n)\) 通常记作 \(\mathrm {id}(n)\)
  • 除数函数 \(\sigma_k(n)=\sum_{d|n}d^k\)\(\sigma_0(n)\) 就是约数个数,记作 \(\tau(n)\)\(\mathrm{d}(n)\)\(\sigma_1(n)\) 就是约数和,记作 \(\sigma(n)\)
  • 大名鼎鼎的欧拉函数 \(\varphi(n)=\sum_{i=1}^n[\gcd(i,n)=1]\)。关于欧拉函数可以看 基础数论学习笔记
  • 本章节的核心莫比乌斯函数 \(\mu(n)=\begin{cases}0&\exist\ d>1,d^2\mid n \\(-1)^{\omega(n)}&\mathrm{otherwise}\end{cases}\),其中 \(\omega(n)\) 表示 \(n\) 本质不同质因子个数。它的积性是显然的。

4.1.2. 狄利克雷卷积(Dirichlet)

由于学习莫比乌斯反演之前需要学会狄利克雷卷积,所以就放在这了。大名鼎鼎的狄利克雷卷积竟沦落到给莫比乌斯反演作铺垫。

定义:设 \(f,g\) 是数论函数,定义它们的狄利克雷卷积为 \(h(x)=\sum_{ab=x}f(a)g(b)\)。显然的,狄利克雷卷积具有交换律,结合律和乘法分配律。它的另一种表达形式为 \(h(x)=\sum_{d|x}f(d)g\left(\dfrac x d\right)\)非常有用

FMT 和 FWT 叫位运算卷积,FFT 和 NTT 叫加法卷积,不难发现狄利克雷卷积实际上是乘法卷积。

狄利克雷卷积有如下性质:两个积性函数的狄利克雷卷积也是积性函数,积性函数的逆元也是积性函数。证明略。

4.1.3. 莫比乌斯函数

因为莫比乌斯函数是积性函数,所以它可以由线性筛求得。

莫比乌斯函数有以下几条性质:

\[\sum_{d\mid n}\mu(d)=\begin{cases}1&n=1\\0&n\neq 1\end{cases} \tag{4.1} \]

首先 \(n=1\) 时显然,否则我们令 \(n\) 的本质不同质因数分别为 \(p_1,p_2,\cdots,p_k\),从中选取 \(i\) 个质数的方案数为 \(\dbinom ki\)。由选奇数个方案数之和等于选偶数个方案数之和可知和为 \(0\)。即 \(k>0\)\(\sum_{i=0}^k1^{k-i}\times\dbinom k i\times (-1)^{i}=(1+(-1))^k=0\)(二项式定定理)。

因此我们证明了 \(\mu*1=\epsilon\)


\[\varphi(n)=\sum_{d\mid n}d\times \mu\left(\dfrac n d\right) \tag{4.2} \]

该式子在推式子时比较有用。可以先证明 \(\varphi*1=\mathrm{id}\),两边同时卷积 \(\mu\)\(\varphi*(1*\mu)=\varphi*\epsilon=\varphi=\mathrm{id}*\mu\)。得证。


\[\sum_{d\mid \gcd(i,j)}\mu(d)=[\gcd(i,j)=1] \tag{4.3} \]

这是极其重要的一个柿子,也是莫比乌斯反演的核心。将 \(\gcd(i,j)\) 带入式 \(4.1\)​​ 即得。


线性筛莫比乌斯函数。

mu[1]=1;
for(int i=2;i<N;i++){
	if(!vis[i])pr[++cnt]=i,mu[i]=-1;
	for(int j=1;j<=cnt&&i*pr[j]<N;j++){
		vis[i*pr[j]]=1;
		if(i%pr[j]==0)break;
		mu[i*pr[j]]=-mu[i];
	}
}

4.1.4. 整除分块

哪里有莫反,哪里就有整除分块。

一个经典的例子是求 \(\sum_{i=1}^n\left\lfloor\dfrac n i\right\rfloor\)\(n\leq 10^{12}\)。注意到不同的 \(\left\lfloor\dfrac n i\right\rfloor\) 的个数实际上是 \(\sqrt n\) 级别的,故使用整除分块:对于一个 \(i\),我们要找到最大的 \(j\) 使得 \(\left\lfloor\dfrac n i\right\rfloor=\left\lfloor\dfrac n j\right\rfloor\),可以证明 \(j=\left\lfloor\dfrac n {\left\lfloor\dfrac n i\right\rfloor}\right\rfloor\)。其实很好理解:找到使 \(\left\lfloor\dfrac n j\right\rfloor=c\) 的最大的 \(j\),只需要用 \(n\) 除以 \(c\) 下取整。

那么,\(l\)​ 从 \(1\)​ 开始,每次令 \(r\gets \min\left(n,\left\lfloor\dfrac n {\left\lfloor\dfrac n l\right\rfloor}\right\rfloor\right)\)​,然后将答案加上 \((r-l+1)\times \left\lfloor\dfrac n l\right\rfloor\)​ 即可。最后 \(l\gets r+1\)​,若大于 \(n\)​ 则退出。

注意当被除数 \(k\) 和枚举上界 \(n\) 不同且 \(k<n\) 时,需要特判 \(\left\lfloor\dfrac k l \right\rfloor=0\)

4.2. 公式

\(f,g\) 是两个数论函数,那么有

\[f(n)=\sum_{d\mid n}g(d)\Rightarrow g(n)=\sum_{d\mid n}\mu(d)f\left(\dfrac n d\right) \tag{4.4} \]

证明:已知 \(g*1=f\),则 \(g*1*\mu=g=f*\mu\)

\[f(n)=\sum_{n\mid d}g(d)\Rightarrow g(n)=\sum_{n\mid d}\mu\left(\dfrac d n\right)f(d) \tag{4.5} \]

证明(来自 OI - Wiki):

\[\begin{aligned}&\sum_{n\mid d}\mu\left(\dfrac d n\right)f(d)\\=&\sum_{k=1}^{+\infty}\mu(k)f(kn)\\=&\sum_{k=1}^{+\infty}\mu(k)\sum_{kn\mid d}g(d)\\=&\sum_{n\mid d}g(d)\sum_{k\mid \dfrac d n}\mu(k)\\=&\sum_{n\mid d}g(d)\epsilon\left(\dfrac d n\right)\\=&g(n)\end{aligned} \]

4.3. 直观理解

只会套皮是不行的,要想熟练运用,不仅要多刷题,也要理解莫反的本质:容斥原理。其中莫比乌斯函数就是容斥系数。也许你会问:容斥系数不应该是 \((-1)^k\) 吗?其实在某种程度上没错,毕竟对比 \((-1)^k\) 与莫比乌斯函数的定义,它们的形式非常相近:只有当 \(x\) 是完全平方数的倍数时容斥系数才为 \(0\)(这其实也暗示了这样的 \(x\) 不同于别的数)。但我们是对于全体自然数做容斥,会有一些奇怪的事情发生:一个自然数被另一个自然数完全包含(这也说明它一定是完全平方数的倍数,接下来会解释),而在容斥原理中,一个集合被另一个集合包含这样的事情是不会发生的。

不妨设接下来有 \(f_n=\sum_{d\mid n}g_d\)

4.3.1. \(n=2\)

\(n=2\) 时,为了求出 \(g_2\),我们只需要用 \(f_2-f_1=(g_2+g_1)-g_1\)。这里已经可以看见容斥的影子了。不妨结合下图以更好理解。

fg7xYD.md.png

4.3.2. \(n=6\)\(\prod p_i\)

\(n=6\) 时,为了求出 \(g_6\),我们首先需要 \(f_6\),但是这样会多加 \(g_1+g_2+g_3\),所以减去 \(f_2+f_3\),但是这样又多减了 \(g_1\),所以我们还应加上 \(f_1\)。结合下图以更好理解。

fg7zfe.md.png

如果 \(n\) 是若干个不同质数 \(p_1,p_2,\cdots,p_k\) 的乘积,那么画出能够表示 \(n\) 的所有约数的韦恩图(\(k>3\) 时画不出来,不过可以理解一下)。\(k\) 个集合相交形成的所有子集就是 \(n\) 的所有约数。比如说,如果有一块区域落在集合 \(p_1\) 和集合 \(p_3\) 中,那么它所表示的约数就是 \(p_1p_3\)。显然,如果 \(x\mid y\),那么区域 \(y\) 包含于区域 \(x\)

fgq6QH.png

图源 https://blog.csdn.net/Summer__show_/article/details/76269088

不妨将 \(f_d\) 看做整块区域 \(d\)(比如说上图中区域 \(30\) 也属于区域 \(6\)),而 \(g_d\) 看做仅属于区域 \(d\) 的部分,然后将所有区域表示的数 \(i\) 替换成 \(\dfrac n i\),那么 \(f_n\) 就表示最外层的大区域,即所有 \(g_d\) 的和,而 \(f_1\) 就表示最里层的小区域,即 \(g_1\),刚好符合 \(f_n=\sum_{d\mid n} g_d\) 的条件。因此,由于 \(f\) 已知,为了得到仅属于区域 \(n\) 的部分所表示的数 \(g_n\),我们只需要进行容斥:加上 \(f_n\),减去 \(f_{p_1},\cdots, f_{p_k}\) …… 不难发现每个数前的容斥系数就是 \(-1\)\(\dfrac n i\) 所含质因子个数次幂,即 \(\mu\left(\dfrac n i\right)\)\(n\) 由互不相同的质因子相乘得到,那么 \(\dfrac n i\) 也如此)。这不就是 \(g_n=\sum_{d\mid n}f_d\mu\left(\dfrac n d\right)\) 吗!

4.3.3. \(n=4\) 及任意自然数

有了上面的经验,你应该很快知道表示约数 \(4\) 的区域被表示约数 \(2\) 的区域 “完全包含”,这里的 \(y\)\(x\) “完全包含” 其实指的是:\(y\) 包含于的所有集合等于 \(x\) 包含于的所有集合且 \(y\mid x\)。画出韦恩图就是一大一小两个圆,其中一个圆完全落在另一个里面。因此,如果计算了 \(2\) 的贡献,那么完全没有必要再算 \(4\) 了,因为 \(4\)\(2\) “完全包含”,所以它们的 “多加/多减状态” 应该是相同的。也就是说算完 \(2\) 的贡献,\(4\) 的贡献也恰好算完,既不多加,也不多减,因而 \(\mu(4)=0\)。不难发现,这种情况仅在一个数是非 \(1\) 的完全平方数的倍数时出现,从而推广至任意自然数。

综上,莫比乌斯函数可以看作\(\N^{+}\) 做容斥时的容斥系数

4.4. 应用

一般用来化简带有 \(\gcd\) 的柿子,几乎所有莫反题都需要用到整除分块。

具体应用可以看 OI-Wiki,抄在博客里其实意义不大。

4.5. 例题

下面所有分式都是下取整。

I. P2522 [HAOI2011]Problem b

二维差分将下界化为 \(1\),然后推式子

\[\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=k] \tag{I.1} \]

\(k\) 搞掉:

\[\sum_{i=1}^{\frac {n}{k}}\sum_{j=1}^{\frac {m}{k}}[\gcd(i,j)=1] \tag{I.2} \]

莫反:

\[\sum_{i=1}^{\frac n k}\sum_{j=1}^{\frac m k}\sum_{d\mid \gcd(i,j)}\mu(d) \tag{I.3} \]

枚举约数 \(d\),记 \(c=\min\left(\dfrac n k,\dfrac m k\right)\)

\[\sum_{d=1}^{c}\mu(d)\sum_{i=1}^{\frac n k}[d\mid i]\sum_{j=1}^{\frac m k}[d\mid j] \tag{I.4} \]

由于 \(1\sim x\)\(y\) 的倍数有 \(\dfrac x y\) 个,故原式化为:

\[\sum_{d=1}^{c}\mu(d)\dfrac n{kd}\dfrac m{kd} \tag{I.5} \]

整除分块即可,时间复杂度 \(\mathcal{O}(n+T\sqrt n)\)

long long 改成 int,11s 变成 5s,离谱。

const int N=5e4+5;

int cnt,pr[N],vis[N],mu[N];
int a,b,c,d,k;
int calc(int x,int y){
	x/=k,y/=k;
	int c=min(x,y),ans=0;
	for(int l=1,r;l<=c;l=r+1){
		r=min(x/(x/l),y/(y/l));
		ans+=(x/l)*(y/l)*(mu[r]-mu[l-1]);
	} return ans;
}
void solve(){
	a=read(),b=read(),c=read(),d=read(),k=read();
	cout<<calc(b,d)-calc(b,c-1)-calc(a-1,d)+calc(a-1,c-1)<<"\n";
}
int main(){
	mu[1]=1;
	for(int i=2;i<N;i++){
		if(!vis[i])pr[++cnt]=i,mu[i]=-1;
		for(int j=1;j<=cnt&&i*pr[j]<N;j++){
			vis[i*pr[j]]=1;
			if(i%pr[j]==0)break;
			mu[i*pr[j]]=-mu[i];
		} mu[i]+=mu[i-1];
	}
	int T=read();
	while(T--)solve();
	return 0;
}

II. SP5971 LCMSUM - LCM Sum

来推式子。

\[\sum_{i=1}^n\mathrm{lcm}(i,n)= n\sum_{i=1}^n\dfrac {i}{\gcd(i,n)} \]

*III. P4318 完全平方数

莫比乌斯函数作为容斥系数的经典例子。

显然答案满足可二分性,于是考虑如何求 \(x\) 以内不含有平方因子的数的个数。仍然是容斥:我们只需要加上所有由偶数个质数相乘的平方的倍数,减去由奇数个质数相乘的平方的倍数。发现这就是 \(\sum_{i^2\leq n}\mu(i)\dfrac{n}{i^2}\),直接暴力求就行了。时间复杂度 \(\mathcal{O}(T\log k\sqrt k)\)

const int N=1e5+5;
int T,n,cnt,pr[N],vis[N],mu[N];
ll calc(ll x){
	ll res=0;
	for(int i=1;i*i<=x;i++)res+=mu[i]*(x/i/i);
	return res;
}

int main(){
	cin>>T,mu[1]=1;
	for(int i=2;i<N;i++){
		if(!vis[i])pr[++cnt]=i,mu[i]=-1;
		for(int j=1;j<=cnt&&i*pr[j]<N;j++){
			vis[i*pr[j]]=1;
			if(i%pr[j]==0){
				mu[i*pr[j]]=0;
				break;
			}
			mu[i*pr[j]]=-mu[i];
		}
	}
	while(T--){
		cin>>n; ll l=n,r=n<<1;
		while(l<r){
			ll m=l+r>>1;
			if(calc(m)<n)l=m+1;
			else r=m;
		} cout<<l<<endl;
	}
	return 0;
}

IV. [BZOJ2986]Non-Squarefree Numbers

双倍经验 P4318 完全平方数。代码从 \(\omega(i)=1\) 时开始容斥,此时容斥系数为 \(1\)(从 \(\omega (i)=0\)\(i=1\) 开始容斥也可以),故筛出的莫比乌斯函数是实际定义的相反数。

template <class T> void cmin(T &a, T b){a = a < b ? a : b;}
template <class T> void cmax(T &a, T b){a = a > b ? a : b;}
bool Mbe;

const int N = 2e5 + 5;

int mu[N], pr[N], vis[N], cnt;
ll n, l, r;
void sieve() {
	for(int i = 2; i < N; i++) {
		if(!vis[i]) pr[++cnt] = i, mu[i] = 1;
		for(int j = 1; j <= cnt && i * pr[j] < N; j++) {
			vis[i * pr[j]] = 1;
			if(i % pr[j] == 0) break;
			mu[i * pr[j]] = mu[i] * -1;
		}
	}
}

ll check(ll lim) {
	ll res = 0;
	for(ll i = 2; i * i <= lim; i++) res += lim / i / i * mu[i];
	return res;
}

bool Med;
int main(){
	fprintf(stderr, "%.2lf\n", (&Mbe - &Med) / 1048576.0);
	sieve(), cin >> n, l = 1, r = n << 2;
	while(l < r) {
		ll m = l + r >> 1;
		if(check(m) < n) l = m + 1;
		else r = m;
	}
	cout << l << endl;
	return 0;
}


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM