二项式反演学习笔记
前言
这里有我关于二项式反演的一些思考和领会,包含理论推导和在信息学竞赛中的应用。网络上的教程都太潦草了,难以深入理解。因此,这里将以详细的证明为主,介绍二项式反演在 OI 中的使用。
如果你只想快速浏览结论,可以点击这里查看结论。
概述
反演是一种将两个函数
二项式反演是一种特殊的反演,用于转化两个具有特殊关系的函数
基础引理
如果你有组合计数类问题的基础,可以跳过引理部分。
引理 :二项式定理
Lemma
考虑从二项式定理证明。普通二项式定理为:
该定理可以通过数学归纳法证明,本文不再详细展开。通过设定
注意到当
引理 :多步容斥
Lemma
记
也就是
不妨记
根据
故该容斥公式成立。
引理 :组合数
Lemma
考虑左式的组合意义,
当然也可以代数证明:
证明 & 推导
模型
Theorem
尽管该模型的实际应用较少,但是作为最基础的反演公式,有必要进行介绍。由于模型的相似性,学习这个模型的证明过程,有助于大家理解后面模型的证明过程。
容斥证明
不妨记
由
由于
发现形式很像,但是还差一步构造。我们假设能构造出一组
不妨记
这两者是等价的,也就证明了
事实上,从这里我们会发现,「二项式反演」和「容斥」有着千丝万缕的联系。如果你在做题时,写着二项式反演,突然意识到式子化开来正是容斥,那么你将会对「二项式反演」的理解更进一步。
代数证明
容斥比较抽象,我们接下来通过代数方法进行证明。我们想要证明左右两式是等价的、可以相互转化的,可以把
形象地展示出来为:
其中,
表示成式子就是:
使用
有二项式定理的样子,运用
显然,
首先将
有了以上基础,接下来我们正式进入「二项式定理」的学习中。接下来将按照从「钦定类问题」到「选择类问题」的顺序,逐步分别分析两大模型。
「钦定类问题」
概述
所谓「钦定类问题」,指的是我们在解决问题时,强制选择某些限制必须满足,不管剩下的限制,即剩下的限制可以满足可以不满足。这个强制选择某些限制必须满足的过程,就是「钦定」。我们发现,在「钦定」后的基础上求解问题,就不需要考虑限制的问题,也就方便了我们对问题的求解。
在「钦定意义」下,我们能够求出「至少」满足
为了方便叙述,假设下文的「至少」和「恰好」均为「钦定意义」下的。
模型 :「至少」 「恰好」
Theorem
此模型用来解决「钦定意义」下「至少」和「恰好」的转化。假设原问题有
注意到,这里
然后,我们考虑由「恰好」表示出「至少」,也就是得出
考虑一种满足了
举个例子:
比如说,我们现在有
我们接下来聚焦于
- 钦定了
两个条件必须满足:
这时,我们会统计到: 四种局面。 - 钦定了
两个条件必须满足:
这时,我们会统计到: 四种局面。 - 钦定了
两个条件必须满足:
这时,我们会统计到: 四种局面。 - 钦定了
两个条件必须满足:
这时,我们会统计到: 四种局面。 - 钦定了
两个条件必须满足:
这时,我们会统计到: 四种局面。 - 钦定了
两个条件必须满足:
这时,我们会统计到: 四种局面。
可见,我们会重复统计,例如我们将
明白了「钦定」的重复计数后,有两种思考方式:
- 一种更直接的思考方式为,我们考虑枚举「钦定」
个限制必须满足后,实际上一共有 个限制被满足,把 乘上上文中提到的重复贡献的系数,求和就得到 。得到:这就是 左侧的式子。 - 另一种绕了个小弯的思考方式是,先考虑如何表示出
。 可以表示为 中减去所有满足了 个限制的局面。又因为上文提到的重复贡献,需要把 次贡献都去除。不难得到:移项后就得到:同样得到 左侧的式子。
该等式阐述了如何由「恰好」表示出「至少」。接下来就是二项式反演的关键步骤,即用「至少」表示出「恰好」。直接推出右边的等式较难,但是如果我们只是为了证明右边等式的正确性,可以借鉴
这是一条恒等式,即证。我们发现,为了求出答案
模型 :「至多」 「恰好」
Theorem
使用「钦定」求出的答案一般来说都是「至少」满足的答案。但是,有一些问题,我们会通过「钦定」
在「钦定意义」下,「至多满足
那么我们不妨尝试套用模型
这就是
这就是
为了更加严谨,当然我们也可以尝试类似证明。留给读者作为习题。
「选择类问题」
概述
「选择类问题」问题下的「至少」/「至多」其实就是「传统意义」下的「至少」/「至多」。但是之所以称作其为「选择类问题」,就是为了和上文提到的「钦定类问题」做区别。和「钦定意义」下的「至少」/「至多」不同,「选择意义」下的「至少」/「至多」并不会重复统计,这是这两类问题不同的关键之所在。「传统意义」下「至多」满足
并且这类问题的限制是等价的,比如染
在「选择意义」下,我们能够求出「至多」满足
为了方便叙述,假设下文的「至少」和「恰好」均为「选择意义」下的。
模型 :「至多」 「恰好」
Theorem
注意,由于直接「选择」求出的是「至多」,我们先来分析「选择意义」下「至多」到「恰好」的转化。
记
由于这
举个例子:
先来关注到一个事实,由于我们的
我们考虑
我们注意到
从这里,我们可以更清晰出所谓「选择」是什么意思。
首先为了得到
考虑我们从
然后类似地,我们想要证明右边等式成立,可以将其带入左边等式。
不出意外地,同样发现这是一条恒等式,说明了
事实上,如果不考虑问题的实际意义,利用模型
点击展开详细证明
设
那么有:
则:
将
模型 :「至少」 「恰好」
Theorem
同样,对于某些问题,我们会通过在
在「选择意义」下,同样有「至少满足
记
这便是
这就是
为了更加严谨,当然我们也可以尝试类似证明。留给读者作为习题。
例题 & 习题
为了更直观地理解二项式反演的实际应用,我们通过例题来分别说明它在「钦定意义」下和「选择意义」下,如何解决「至少」/「至多」与「恰好」之间的转化关系。
例一、洛谷 P6512 [CEOI2010 day2] pin
「钦定意义」下「至少」与「恰好」的转化。
题意简述:
yzh 给你
首先,「相同」往往比「不同」更好考虑,令
首先,将第
在处理这类问题时,套路化地,若我们先计算出「至少」或「至多」满足
此题我们不妨考虑「钦定」
具体来说,我们枚举并「钦定」
点击查看代码
#include <iostream> #include <cstdio> #include <unordered_map> using namespace std; using ull = unsigned long long; int n, m; char str[50010][5]; long long f[5]; const int frac[5] = {1, 1, 2, 6, 24}; inline int C(int n, int m) { return frac[n] / frac[m] / frac[n - m]; } signed main() { scanf("%d%d", &n, &m), m = 4 - m; for (int i = 1; i <= n; ++i) scanf("%s", str[i]); for (int mask = 0; mask < 1 << 4; ++mask) { long long res = 0; unordered_map<ull, int> table; for (int i = 1; i <= n; ++i) { ull hsh = 0; for (int j = 0; j < 4; ++j) { hsh *= 131; if (mask & 1 << j) hsh += str[i][j]; } res += table[hsh]; ++table[hsh]; } f[__builtin_popcount(mask)] += res; } long long ans = 0; for (int k = m; k <= 4; ++k) { if ((k - m) & 1) ans -= C(k, m) * f[k]; else ans += C(k, m) * f[k]; } printf("%lld", ans); return 0; }
例二、「FJWC2020Day4-IJN」夕张的改造
「钦定意义」下「至多」与「恰好」的转化。
题意简述:
给定一棵
一句话题解:Prufer 序列求出「钦定意义」下「至多」
更详细的题解及代码见我的题解。
例三、洛谷 P6076 [JSOI2015] 染色问题
「选择意义」下「至多」与「恰好」的转化。
题意简述:
yzh 有一个
- 棋盘的每一个小方格既可以染色,也可以不染色。
- 棋盘的每一行至少有一个小方格被染色。
- 棋盘的每一列至少有一个小方格被染色。
- 每种颜色都在棋盘上出现至少一次。
首先,将「每一」替换成「恰好」,原题转化成要求棋盘中「恰好」有
考虑使用「选择」的方式,一步步拆解问题。
首先拆掉颜色的限制。考虑计算出「选择意义」下,「至多」出现
类似地,逐步拆去列、行的限制,最后得出这样一个问题:一个
再一步步用
时间复杂度是
点击查看代码
#include <iostream> #include <cstdio> using namespace std; const int mod = 1e9 + 7; constexpr inline int add(const int a, const int b) { return a + b >= mod ? a + b - mod : a + b; } constexpr inline int sub(const int a, const int b) { return a - b < 0 ? a - b + mod : a - b; } constexpr inline int mul(const int a, const int b) { return 1ll * a * b % mod; } int n, m, c, frac[520], ifrac[520], Inv[520]; int f[520], pw[520 * 520]; int C(int n, int m) { return mul(frac[n], mul(ifrac[m], ifrac[n - m])); } signed main() { scanf("%d%d%d", &n, &m, &c); frac[0] = ifrac[0] = 1; for (int i = 1; i <= 400; ++i) { frac[i] = mul(frac[i - 1], i); Inv[i] = i == 1 ? 1 : sub(0, mul(mod / i, Inv[mod % i])); ifrac[i] = mul(ifrac[i - 1], Inv[i]); } int ans = 0; for (int t = 0; t <= c; ++t) { pw[0] = 1; for (int i = 1; i <= n * m; ++i) pw[i] = mul(pw[i - 1], t + 1); for (int j = 0; j <= m; ++j) { for (int i = 0; i <= n; ++i) { int res = mul(pw[i * j], mul(mul(C(n, i), C(m, j)), C(c, t))); if (((c - t) ^ (m - j) ^ (n - i)) & 1) ans = sub(ans, res); else ans = add(ans, res); } } } printf("%d", ans); return 0; }
其实可以优化。拆限制不要全拆掉,到了这个问题其实可以停下了:一个
所以答案为:
时间复杂度:
点击查看代码
#include <iostream> #include <cstdio> using namespace std; const int mod = 1e9 + 7; constexpr inline int add(const int a, const int b) { return a + b >= mod ? a + b - mod : a + b; } constexpr inline int sub(const int a, const int b) { return a - b < 0 ? a - b + mod : a - b; } constexpr inline int mul(const int a, const int b) { return 1ll * a * b % mod; } constexpr inline int pow(const int a, const int p) { int res = 1, base = a % mod, b = p; while (b){ if (b & 1) res = mul(res, base); base = mul(base, base), b >>= 1; } return res; } int n, m, c, frac[520], ifrac[520], Inv[520]; int f[520]; int C(int n, int m) { return mul(frac[n], mul(ifrac[m], ifrac[n - m])); } signed main() { scanf("%d%d%d", &n, &m, &c); if (n > m) swap(n, m); frac[0] = ifrac[0] = 1; for (int i = 1; i <= 400; ++i) { frac[i] = mul(frac[i - 1], i); Inv[i] = i == 1 ? 1 : sub(0, mul(mod / i, Inv[mod % i])); ifrac[i] = mul(ifrac[i - 1], Inv[i]); } int ans = 0; for (int t = 0; t <= c; ++t) { for (int j = 0, pw = 1; j <= n; ++j, pw = mul(pw, t + 1)) { int res = mul(pow(sub(pw, 1), m), mul(C(c, t), C(n, j))); if (((c - t) ^ (n - j)) & 1) ans = sub(ans, res); else ans = add(ans, res); } } printf("%d", ans); return 0; }
例四、yzh 的生日礼物
「选择意义」下「至少」与「恰好」的转化。
题目描述:
yzh 生日要到啦!你想为她准备一份精美的生日礼物。以你对她的了解,她早就喜欢上一个价值 由于你的钱包吃紧,由于你希望自己亲手制作一个送给她,因为虽然你不懂浪漫,但你认为亲手制作的是
这个项链由
你希望在她
你和她之间的点点滴滴又浮现在你的脑海中,你感到幸福、也感到快乐。你忘不了你们在一起看过的每一场电影,忘不了你们一同在漫天璀璨星辰下散步,更忘不了最初见到彼此的那一瞬间的悸动。
想到这,你脑中突然蹦出一个问题:对于
题意简述:
给出一个长为
「恰好」没出现
题目不难,可能有一个
例五、错排
题意简述:
求长为
为了哄好 yzh,你需要使用二项式反演的解法。
把「
- 「选择意义」下「至多」与「恰好」的转化。
考虑「选择意义」下「至多」满足 个限制的答案,即错排的数字只能从 中「选择」,剩下 种颜色没有错排,待在各自的位置上。这时,方案数就是 ,这是没有重复计数的,符合「选择意义」。用 反演即可。答案 。 - 「钦定意义」下「至多」与「恰好」的转化。
考虑「钦定意义」下「至多」满足 个限制的答案。我们钦定 个限制必不满足(即 ),剩下 个限制随便排,方案数即为 。用 反演即可。答案同样为 。
从这题我们发现「钦定」和「选择」有时候也是可以相互转化的。
习题
这里总结了一些习题,大家可以练练手。
- 已经没有什么好害怕的了 - 洛谷 P4859;
- Another Filling the Grid - Codeforces 1228E;
- NEQ - AtCoder ABC172E;
- [COCI2009-2010#4] PALACINKE - 洛谷 P5188;
- BZOJ2839 集合计数;
- [COCI2021-2022#4] Šarenlist;
- [ARC115E] LEQ and NEQ;Non-equal Neighbours;Non-equal Neighbours;
- [NOI Online #2 提高组] 游戏;
- [JSOI2011] 分特产;
- [COCI 2011/2012 #6] KOŠARE 礼物沙龙;Jzzhu and Numbers;KOSARE;
欢迎补充。
总结
二项式反演为我们提供了一种灵活处理「至少」/「至多」与「恰好」之间转换的方法。在信息学竞赛中的许多问题,特别是涉及到组合计数、限制条件的题目中,二项式反演是非常有效的工具。
并且我们弄清算出的「至少」/「至多」有没有重复计数的问题,思考是「钦定类问题」还是「选择类问题」,从而选择正确的模型解决问题。
对于式子的记忆和熟练运用,需要读者不断练习巩固。「钦定类问题」下「至少」
希望这篇文章能帮助你更好地理解和应用二项式反演。
结论
模型
模型 :「至少」 「恰好」
「钦定类问题」
「选择类问题」
模型 :「至多」 「恰好」
「钦定类问题」
「选择类问题」
<!-- script --> <script> sidebarToggle() </script>
本文作者:XuYueming,转载请注明原文链接:https://www.cnblogs.com/XuYueming/p/18397758。
若未作特殊说明,本作品采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】