【笔记】二项式反演

很多时候如果元素是等价的,那么容斥本质上就是 \(i=0\) 的二项式反演。【[ARC096E] Everything on It

其实好像所谓广义容斥就是二项式定理(


1 反演常⽤形式

这里令 \(N\) 为总的 不同 的元素个数。

1.0 关于「钦定」的概念

对于 \(N\) 个元素,我们人为认定其中满足某些特殊性质(一般即为题目中最后要求的答案所满足的要求)的元素。

似乎可以认为钦定的本质就是 选择

注意到,如果钦定的元素,与元素本身无关,而只与元素间关系有关(比如元素个数(一般是这个)、元素间大小关系)。对于两种不同的这样的钦定是可以在一定情况下是等价的。

(说的好玄乎,具体可以参见下面的例题((


1.1 二项式反演 1

\(g(n)\) 表示从 \(N\) 个不同元素 钦定/选至多 \(n\) 个元素形成特定结构的方案数;

\(f(n)\) 表示 恰好 使用 \(n\) 个不同元素(且这 \(n\) 个元素均是被钦定的)形成特定结构的总方案数。

若已知 \(f(n)\)\(g(n)\),那么显然有:

\[g(n)=\sum_{i=0}^{n}{n\choose i} f(i) \]

若已知 \(g(n)\)\(f(n)\),那么:

\[f(n)=\sum_{i=0}^{n}{n\choose i}(-1)^{n-i} g(i) \]


1.2 二项式反演 2

\(g(n)\) 表示从 \(N\) 个不同元素 钦定/选至少 \(n\) 个元素形成特定结构的方案数;

\(f(n)\) 表示 恰好 使用 \(n\) 个不同元素(且这 \(n\) 个元素包含所有被钦定的)形成特定结构的总方案数。

若已知 \(f(n)\)\(g(n)\),那么显然有:

\[g(n)=\sum_{i=n}^{N}{i\choose n} f(i) \]

若已知 \(g(n)\)\(f(n)\),那么:

\[f(n)=\sum_{i=n}^{N}{i\choose n}(-1)^{i-n} g(i) \]


上述已知 \(g(n)\)\(f(n)\) 的过程,就称为 「二项式反演」

证明可以将前一个式子的 \(g(n)\) 代到后一个式子中,并使用组合恒等式做一些「转化与化归」即可。


2 例题

一个 Trick 是:

\[f(n)=\sum_{i=n}^{N}{i\choose n}(-1)^{i-n} g(i) \]

如果 \(g\) 是一个求和式,那么交换求和顺序,可以对 \(\sum_{i=n}^{N}{i\choose n}(-1)^{i-n}\) 补一个 \(0\) 次项之后用二项式定理【 「BZOJ2863」愤怒的元首


2.1 二项式反演 2

下面的一部分比较远古了,\(g,f\) 的一些定义可能不太对。


「BZOJ 2839」集合计数

\(g(n)\) 表示最终交集中元素包含了 钦定\(n\) 个元素的方案数;

\(f(n)\) 表示最终交集中 至少\(n\) 个不同元素(且这 \(n\) 个元素包含所有被钦定的)的总方案数。

由 二项式反演 2 可知:

\[f(n)=\sum_{i=n}^{N}{i\choose n}(-1)^{i-n} g(i) \]

下考虑如何求解 \(g(i)\)

  • 对于钦定的 \(i\) 个元素,其方案数为 \({n\choose i}\)
  • 对于非钦定的 \(n-i\) 个元素,她们将会出现 \(2^{n-i}\) 个子集,于是子集合的选取方案数进而为 \(2^{2^{n-i}}\)
  • 注意,在计算子集个数时,算上了空集;最后再选取的子集时,亦算上了一个子集都不选的方案。而这两种方案本质上是同一种,即非钦定的元素一个都不选。故最终的 \(g(i)={i\choose i}(2^{2^{n-i}}-1)\)

预处理后,时间复杂度为 \(O(n)\)。(然而下面的代码并没有预处理((

Code
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5, mod = 1e9 + 7;
int n, k;
struct mint {
	int val;
	mint (long long x=0) { val = x%mod; }
	inline mint operator + (mint x) { return (1ll*val + x.val) % mod; }
	inline mint operator - (mint x) { return (1ll*val - x.val + mod) % mod; }
	inline mint operator * (mint x) { return (1ll*val * x.val) % mod; }
	inline mint operator += (mint x) { return *this = *this + x; }
	inline mint operator -= (mint x) { return *this = *this - x; }
	inline mint operator *= (mint x) { return *this = *this * x; }
} ans, fac[N];
mint qpow (mint a, mint b) {
	mint res = 1;
	for (; b.val; b.val >>= 1, a *= a)
		if (b.val & 1) res *= a;
	return res;
}
mint qpow2 (long long a, long long b) {
	long long res = 1;
	for (; b; b >>= 1, a = (1ll*a*a)%(mod-1))
		if (b & 1) res = (1ll*res*a)%(mod-1);
	return res;
}
mint inv (mint x) { return qpow(x, mod-2); }
void init_fac (int _n) {
	fac[0] = 1;
	for (int i = 1; i <= _n; i++) fac[i] = fac[i-1] * i;
}
mint C (int n, int m) { return fac[n] * inv(fac[m]*fac[n-m]); } 
mint g (int i) {
	return C(n,i) * (qpow(2, qpow2(2, n-i)) - 1);
}
int main () {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin >> n >> k;
	init_fac(n);
	for (int i = k; i <= n; i++) {
		// printf("%lld %lld %lld %lld\n", C(i,k), C(n,i), ((i-k)&1?-1:1), g(i));
		if ((i & 1) == (k & 1))
			ans += C(i,k) * g(i);
		else
			ans -= C(i,k) * g(i);
	}
	cout << ans.val;
	return 0;
}

「BZOJ3622」已经没有什么好害怕的了

\(g(n)\) 表示最终配对方案中包含了 恰有\(n\) 对元素,对每个元素满足 \(a_i > b_i(1\le i\le n)\) 的方案数;

\(f(n)\) 表示最终交集中 至少\(n\) 个不同元素,满足 \(a_i > b_i(1\le i\le n)\)(且这 \(n\) 个元素包含所有被钦定的)的总方案数。

由于总的对数是确定的 \(n\),所以答案即为 \(f(\frac{n+k}2)\)

由 二项式反演 2 可知:

\[f(n)=\sum_{i=n}^{N}{i\choose n}(-1)^{i-n} g(i) \]

下考虑如何求解 \(g(i)\)

首先对 \(a,b\) 排序。

考虑 DP,令 \(dp[i][j]\) 表示对于 \(a\) 的前 \(i\) 项,配对了 \(j\)\(a_i>b_i\)

\(\lambda(x)\) 表示对于 \(x\) 有多少个 \(b_i\) 是小于 \(x\) 的。有如下状态转移方程:

\[dp[i][j] = dp[i-1][j-1]\times \lambda(a_i) + dp[i-1][j] \]

于是 \(g(i)=dp[n][i]\times (n-i)!\)。至少有 \(i\) 对满足,剩下的 \((n-i)\) 个元素随便排即可。

时间复杂度为 DP 的 \(O(n^2)\)


「CF1228E」 Another Filling the Grid

\(g(n)\) 表示最终方案中包含了 恰有\(n\) 对元素,对每个元素满足 \(a_i > b_i(1\le i\le n)\) 的方案数;

\(f(n)\) 表示最终交集中 至少\(n\) 个不同元素,满足 \(a_i > b_i(1\le i\le n)\)(且这 \(n\) 个元素包含所有被钦定的)的总方案数。

咕。


「CF997C」Sky Full of Stars

\(f(i,j)\) 表示最终方案中 恰有 \(i\) 行相同的,\(j\) 列相同的;

\(g(i,j)\) 表示最终方案中 至少 \(i\) 行相同的,\(j\) 列相同的。

答案即为:\(Ans=3^{n\times n}-f(0,0)\)

由 高维二项式反演 2 可知:

\[f(n,m)=\sum_{i=n}^{N}\sum_{j=m}^{N}(-1)^{i-n+j-m}{i\choose n}{j\choose m}g(i,j) \]

特别的 \(n=m=0\) 时,有:

\[f(0,0)=\sum_{i=0}^{n}\sum_{j=0}^{n}(-1)^{i+j}g(i,j) \]


下考虑如何求 \(g(i,j)\),再求 \(f(0,0)\)

分类讨论:

  1. \(i\ne0\ \text{and}\ j\ne0\)

    此时,一定有行列相交,所以这 \(i\) 行和 \(j\) 列中的颜色都是一样的。

    \(\begin{aligned}g(i,j)=3^{(n-i)(n-j)}{n\choose i}{n\choose j}\end{aligned}\times3\)

    \[\begin{aligned}f(0,0)&=\sum_{i=1}^{n}\sum_{j=1}^{n}(-1)^{i+j}3^{(n-i)(n-j)+1}{n\choose i}{n\choose j}\\&=\color{lightgrey}\sum_{d=2}^{2n}(-1)^d3^{n^2-nd+1}{n\choose i}\sum_{i=1}^{d-1}3^{id-i^2}{n\choose d-i}&\color{lightgrey}\text{【不太行,组合数前的系数难搞】}\\&=\sum_{i=1}^{n}(-1)^i3^{n^2-ni+1}{n\choose i}\sum_{j=1}^{n}{n\choose j}(-1)^{j}3^{j(n+i)}\\&=\sum_{i=1}^{n}(-1)^i3^{n^2-ni+1}{n\choose i}\sum_{j=1}^{n}{n\choose j}1^{n-j}{\left(-3^{(i-n)}\right)^j}\\&=\sum_{i=1}^{n}(-1)^i3^{n^2-ni+1}{n\choose i}\left(\left(1-3^{(i-n)}\right)^n-1\right)&\text{【二项式定理】}\\\end{aligned} \]

    然后就可以 \(O(n\log n)\) 做了。

  2. \(i=0\ \text{and}\ j\ne 0\)

    此时,另外的 \(j\) 列每两列之间不一定颜色相同。

    \(\begin{aligned}g(0,j)=3^{n(n-j)}{n\choose j}\times 3^j\end{aligned}\)

    直接算即可。

  3. \(i\ne0\ \text{and}\ j= 0\)

    \(i=0\) 同理。

    \(\begin{aligned}g(i,0)=3^{n(n-i)}{n\choose i}\times 3^i\end{aligned}\)

    直接算即可。

  4. \(i=0\ \text{and}\ j=0\)

    完全乱放。

    \(g(0,0)=3^{n\times n}\)


综上所述:

\[Ans=3^{n\times n}-\left(\sum_{i=1}^{n}(-1)^i3^{n^2-ni+1}{n\choose i}\left(\left(1-3^{(i-n)}\right)^n-1\right)+2\times\sum_{i=1}^n(-1)^i3^{n(n-i)}{n\choose i}\times 3^i+3^{n\times n}\right) \]

posted @ 2023-12-18 16:37  CloudWings  阅读(13)  评论(0编辑  收藏  举报