容斥and反演
何为容斥? 何为反演?
前置知识
组合数的一些知识
什么是容斥
一个经典容斥
利用容斥可以做到使用交集表示并集
稍微变形一下, 也可以使用并集表示交集
众所周知的一个关系式子是:
$ \overline{A} \cap \overline{B} = \overline{A \cup B}$, $ \overline{A} \cup \overline{B} = \overline{A \cap B}$
利用这个式子就可以完成上边的要求
我们考虑推广, 交集可以理解成至少 \((\ge S)\) , 并集可以理解成至多 \((\le S)\)
你有 \(k\) 个属性
设函数 \(f(S)\) 表示至少满足 \(S\) 集合的元素个数, 特殊地, \(f(\emptyset) = 0\)
设函数 \(g(S)\) 表示至多满足 \(S\) 集合的元素个数
有式子
证明: 考虑 有 \(n\) 个属性的元素的贡献
只会对答案产生一个贡献
一般化
考虑将一个问题分成几个限制很小的几部分, 但是会算重复, 所以使用容斥系数干掉这些东西, 让贡献唯一
举例
- 比如一种问题是:
就是上述的经典容斥
有一个属性集合\(k\),然后有一个可以查询至少满足属性集合 \(S\) 的物品贡献的函数 \(q(S)\)
同时还有一个函数 \(g(k)\),对于一个有 \(k\) 个属性的物品,它会对答案产生 \(g(k)\) 的贡献
需要确定一个容斥系数 \(f(x)\),使得式子 \(g(n) = \sum_{i=1}^{n}{{n}\choose{i}}f(i)\) 成立
答案是全集 \(U\)
\(Answer = \sum_{T \subseteq U} q(T) f(\left| T \right|)\)
对于容斥系数可以使用 \(n^2\) 的递推推出来, 有时候也可以使用反演
具体地: 因为有式子: \(g(n + 1) = \sum_{i=1}^{n + 1}{{n + 1}\choose{i}}f(i)\) 成立, 已知 \(1-n\) 的 \(f\) 数组值, 所以可以把 \(n + 1\) 解出来
像这种右边有一个组合数的东西, 这很指数生成函数:
然后就可以多项式求逆 \(O(n log_n)\)
- 另一种例子
比如一类段式的 \(DP\)
通过几段拼成一个整段, 但是整段的拼接方案非常多, 所以使用容斥系数让他的贡献唯一
通常容斥系数的取值决定于段长
子集反演
有这样一个式子:
要求用 \(f\) 表示 \(g\) 完成反演, 设 \(F(x)\)
要求容斥系数有 \(\sum_{U \subseteq T \subseteq S} F(\left| T \right|) = [U == S]\)
可以递推求得, 或者推一下, 众所周知 \([a == b] = 0^{b - a}\)
所以 \(F(i + \left| U \right|) = (-1)^{i} 或者 (-1)^{\left| S \setminus U \right| - i}\)
显然后者更加简单, 所以 \(F(x) = \left| S \right| - x\)
所以反演得到:
运用相同的思路可以得到另一组对应的式子:
这就是子集反演
当然有实际意义, 对于第一种形式, \(f\) 可以表示的是 至多 (所选集合是要求的一个子集) , \(g\) 可以表示的是 恰好 (所选集合相等)
对于第二种形式, \(f\) 可以表示的是 至少 , \(g\) 可以表示是 恰好
二项式反演
三组式子:
以第一个式子的推导为例子
已知: \(f_n = \sum_{i=0}^n(-1)^i{{n}\choose{i}}g_i\)
所以要求 \(\sum_{i=j}^n(-1)^j{{i}\choose{j}}F(i) = 0^{n - j}\)
目的很明确了, 我们需要 \({{i}\choose{j}} \rightarrow {{n - j}\choose{i - j}}\) 正好有一个组合数式子
所以 \(F(i)\) 有一项为 $ {{n}\choose{i}} $
发现它多产生的贡献: \({{n}\choose{j}}\) 在\(j == n\) 时为 \(1\) 可以不用管
所以 \(F(i + j) = (-1)^{i - j} = (-1)^{i - j} \times (-1)^{2 \times j} = (-1)^{i+j}\)
所以 \(F(i) = {{n}\choose{i}} (-1)^i\)
当然也有实际意义, 我们发现这个其实和子集反演差不多, \(g\) 表示的是恰好, \(f\) 表示的是至多或者至少
应用
错排问题
我们可以钦定一些位置, 所以可以保证在自己位置的数的个数 \(\ge\) 一个数
所以可以直接反演到 \(=\) , \(g_0\) 即为所求
具体地, \(f_i = {{n}\choose{i}}(n - i)!\)
有 \(f_k = \sum_{i=k}^n{{i}\choose{k}}g_i\)
直接反演得到 \(g_0 = \sum_{i=0}^n(-1)^{i}{{i}\choose{0}}f_i = \sum_{i=0}^n(-1)^{i}{{n}\choose{i}}(n - i)!\)
\(g_0 = \sum_{i=0}^n(-1)^{i}{{n}\choose{i}}(n - i)! = \sum_{i=0}^n(-1)^{i}\frac{n!}{i!}\)
继续扩展发现当 \(n \rightarrow n+1\) 我们是有递推式子的 \(answer_{n + 1} = (-1)^{n + 1} + (n + 1)answer_n\)
解的个数
方程 \(\sum_{i = 1}^n x_i = b\)
\(l_i \le x_i \le r_i \le 10^{12}, n \le 15\)
有下限好做, 就是插板, 上限我们可以钦定一些超过, 上限就变成了下限, 然后随机就是 \(\ge\) , 因为每一个限制不同, 所以上子集容斥
加强版本:
\(\sum_{i}^{n_1} X_i > \sum_{i}^{n_2} Y_i\)
\(X_i \in [l_i, r_i], Y_i \in [l_i, r_i], n_1 + n_2 \le 15\)
求解的个数
移向的话, 负数不好处理, 考虑把 \(X_i\) 映射为 \(r_i - X_i + 1\) 顺便也都把下限都干掉, 于是设
\(r_i - x_i= X_i, l_i + y_i = Y_i, 0 \le x_i, y_i \le r_i - l_i\)
原式子就可以变成
\(\sum_i x_i + \sum_i y_i < \sum_i r_i - \sum_i l_i\)
怎么把小于变成等于号? 先变成小于等于号
\(\sum_i x_i + \sum_i y_i \le \sum_i r_i - \sum_i l_i - 1\)
然后
\(\sum_i x_i + \sum_i y_i + k = \sum_i r_i - \sum_i l_i - 1\)
上容斥
Min-Max容斥
如何用 \(Min\) 来表示 \(Max ?\)
\(Max(S) = \sum_{\emptyset \not= T \subseteq S} Min(T) F(\left| T \right|)\)
将原数组从小到大排序后, 我们需要满足的式子就是:
\([x = n] = \sum_{i=0}^{n-x} {{n - x}\choose{i}} F(i + 1)\)
这是一个二项式反演的形式, 写的更具体一点就是:
\([n - x = 0] = \sum_{i=0}^{n-x} {{n - x}\choose{i}} F(i + 1)\)
反演得到: \(F(x) = (-1)^{x + 1}\)
所以有下边的两组式子:
根据期望的线性性, 可以得到他在期望下也是成立的, 这里的取 \(max\) 以及 \(min\) 是对随机变量函数进行的取 \(max\) 操作
当然如果我们将推导式子中的 \([x=n]\) 改为 \([x=n-k+1]\) 就可以求得 \(kthMax\) , 也是二项式反演的形式, 得到
我们通过整数唯一分解定理, 和 \(gcd\) 的定义, 我们可以知道, \(gcd\) 相当于对每一项的指数取 \(min\) , \(lcm\) 相当于取 \(max\) 所以根据这个可以得到 \(gcd\) 与 \(lcm\) 之间的关系
这个在求 \(gcd\) 比较容易的时候是比较好用的, 比如 \(Fib\)
前缀和与差分
这个为什么会在这里? 因为他用到了容斥的思想, 以及根一个反演有关
定义原数组 \(a\), 前缀和数组 \(s\)
前缀和
根据一二维的推广, 我们不难列出一下的式子:
\(\begin{aligned} s_{x_{1}, x_{2}, \cdots, x_{k}}= & a_{x_{1}, x_{2}, \cdots, x_{k}}+\sum_{i_{1}=0}^{1} \sum_{i_{2}=0}^{1} \cdots \sum_{i_{k}=0}^{1} \\ & {\left[\sum_{j=1}^{k} i_{j}>0\right]F\left(\sum_{j=1}^{k} i_{j}\right) s_{x_{1}-i_{1}, x_{2}-i_{2}, \cdots, x_{k}-i_{k}} } \end{aligned}\)
可以根据哪些位置是 \(i_j\) 是可以有值的列出一个需要满足的式子
具体地, 假设 \(n (n \not= 0)\) 个位置的 \(i_j\) 是有可以有值, 那么就需要满足:
\(\sum_{i = 1}^n {{n}\choose{i}} F(i) = 1\)
然后 \(F(i) = (-1)^{i + 1}\)
所以有:
差分
前缀和的逆运算, 直接把前缀和的式子移向变换就可以了
莫比乌斯反演
定义迪利克雷卷积: \(A \times B = C\)
\(c_n = \sum_{d \mid n} a_d b_{\frac{n}{d}}\)
给出反演式子
考虑如何构造 \(\mu\) 使得上述式子成立
考虑迪利克雷卷积卷 \(1\) 的本质: 前缀和
根据整数唯一分解定理, 然后不难得出这个式子
这本质就是一个前缀和
所以 \(\mu\) 要求的就是差分操作, 于是考虑差分容斥式子中的 \((-1)^{\left(\sum_{j=1}^{k} i_{j}\right)}\)
不难得到 \(\mu\) 的定义式子:
\(\mu(n)= \begin{cases} 1&n=1\\ 0&n\text{ 含有平方因子}\\ (-1)^k&k\text{ 为 }n\text{ 的本质不同质因子个数}\\ \end{cases}\)
应用
对于处理 \(gcd(a, b) = c\) 的情况, 我们可以求出 \(gcd(a, b) \mid i\) 的情况
这是一个前缀和, 然后用莫比乌斯做一遍差分就可以得到答案
单位根反演
对于一个数列, 我们想要求出 \(\sum_{i} a_i [k \mid i]\)
也就是说, 我们想要求 \([k \mid i]\) 的表达式
直接给出式子, 不知道怎么推出来的:
后边是一个等比数列求和, 直接考虑 \(\frac{r^n - 1}{r - 1}\) , 其中我们发现 \(r^n\) 永远为 \(1\) , 所以当 \(r - 1 \not= 0\) 时, 等比数列求出来的都是 \(0\) , 当 \(\omega_n^k = 1\) 时 , \(n \mid k\) 带入原式子, 值为 \(1\)
对于这个数列, 我们构造生成函数 \(F(x) = \sum_{i = 1}^n a_ix^i\)
答案就是
斯特林数
第二类斯特林数
表示 \(n\) 个元素 \(k\) 种划分的方案数
\(n\) 个盒子 \(m\) 个小球, 根据组合意义可以得到:
实现了普通幂转下降幂
一个应用是可以把 \(F(x) = \sum a_i x^i\) 转为 \(F(x) = \sum b_i x^{\underline{i}}\)
当然还有递推式子, 考虑这样一个问题: \(m\) 个元素恰好划分为 \(k\) 种的方案数
是不是可以用二项式反演: \(f_i = i^m\) 但是我也可以用第二类斯特林数表示出来 \(g_i = i! \begin{Bmatrix}m\\ i\end{Bmatrix}\)
所以有 \(k! \begin{Bmatrix}m\\ k\end{Bmatrix} = \sum_{i=0}^k(-1)^{k-i}{{k}\choose{i}} i^m\)
把组合数拆开, 写成卷积形式
第一类斯特林数
\(n\) 个元素划分为 \(k\) 个环的方案数
\(\begin{bmatrix}n\\ k\end{bmatrix}=\begin{bmatrix}n-1\\ k-1\end{bmatrix}+(n-1)\begin{bmatrix}n-1\\ k\end{bmatrix}\)
可以实现上指数幂转普通幂
\(F_n(x) = \sum \begin{bmatrix} n\\ i\end{bmatrix} x^i\)
\(F_n(x) = F_{n-1}(x) x + (n - 1)F_{n-1}(x) = F_{n - 1}(x) (x + n - 1)\)
上指数幂与下指数幂
可以构造得到
\(x^{\underline{n}} = (-1)^{n}(-x)^{\overline{n}}\)
\(x^{\overline{n}} = (-1)^{n}(-x)^{\underline{n}}\)
聪明的人已经猜到要干什么了
普通幂转下降幂转上升幂转普通幂
就可以得到
反转公式
所以有反转公式:
同理可以得到:
斯特林反演
将反转公式带入就可以得到
容斥系数的计算方法
递推
根上边说的一样
直接上例题
- 求不存在一个子序列为长度大于 \(m\) 的公差为 \(1\) 或 \(-1\) 的等差数列的排列个数.
\(n, m \le 200\)
排列一定可以划分成若干个等差数列, 这样也将值域划分成了若干段, 所以考虑对值域进行分段的 \(DP\) 就可以
需要知道每段的长度以及相对大小就可以确定唯一一种方案, 于是考虑分段 \(DP\) , \(f_{i, j}\) 前 \(i\) 个位置, \(j\) 段
转移 \(f[i][j] = \sum_x f[x][j - 1] \times j \times (1 + [i - x > 1])\)
还需要考虑上升序列还是下降序列, 所以有乘 \(2\)
这样是不对的, 一种方案会被算重复, 考虑计算容斥系数!
考虑在原\(DP\)上乘上这样一个东西:
\(f[i][j] = \sum_x f[x][j - 1] \times j \times (1 + [i - x > 1]) \times F[i - x]\)
考虑一个方案的一个极长等差数列, 它的计数次数, 根据乘法原理, 总段的计数次数就是乘起来的结果
考虑一个极长的等差数列, 考虑把他划分成几段, 然后用乘法原理乘起来, 枚举最后一段长度, 发现如果前面长度 \(> m\) 前边方案数显然 \(=0\) 所以总贡献就是 \(0\) 否则就是 \(1\)
不难得到这个等式:
\(\sum_{i=0}^{min(n-1, m)} F_{n-i} = [n \le m]\)
分类讨论去掉这些东西, 然后推式子, 发现有:
\(F[1] = 1, F[n] = 0(1 < n\le m), F[n] = -\sum_{i=1}^{m}F[n - i] (n > m)\)
生成函数
使用生成函数, 不用 \(n^2\) 的 递推
考虑容斥系数的生成函数 \(F = \sum_{i} f_ix^i\)
考虑它的贡献 \(H = 1 + F + F^2 + F^3... = \frac{1}{1 - F}\)
这样就可以反解出容斥系数
在考虑转移生成函数 \(G = \sum_i a_if_ix^i\)
答案就是 \([x^m] \frac{1}{1 - G}\)
用几道题来说明
- 上面的题目
直接写出 贡献生成函数 \(G = 1 + x + x^2 + .. + x^m = \frac{1 - x^{m + 1}}{1 - x}\)
所以 \(G = \frac{1}{1 - F}\)
直接解出来 \(F = \frac{x - x^{m + 1}}{1 - x^{m + 1}}\)
分母展开, 乘上分子得到 \(F = \sum_i x^{i(m + 1) + 1} - \sum_i x^{(i + 1)(m + 1)}\)
多项式加减法是简单的, \(O(n)\) 求得, 和上边解出来是一样的, 不用动脑子
给出 \(a,b,c\),求由 \(a\) 个 A,\(b\) 个 B,\(c\) 个 C 构成的字符串数量,使得不存在子串 ABC
,BCA
和 CAB
。\(1 \leq a,b,c \leq 10^6\)
考虑划分成连续的几段, 然后容斥
分类讨论得到
然后使用三元生成函数
\(Answer = \frac{1}{1 - G} = (1 - xyz) \sum_{i \ge 0} (x + y + z - 2xyz)^i\)
然后需要求 \([x^ay^bz^c]Answer\)
枚举 \(xyz\) 的个数, 然后做可重集的排列