容斥 dp
容斥系数一般是 ( − 1 ) ∣ S ∣ (-1)^{|S|} (−1)∣S∣。
初学容斥原理时都做过这样的一道题。有一张 n × m n \times m n×m 的棋盘,在上面染色,要求任意一行、任意一列的颜色都不完全相同。这是一个模型
全部 − - − 至少一个 + + + 至少两个 − ⋯ = - \cdots = −⋯=一个也没有。
所以我们枚举一下有多少行颜色一定相同,有多少列颜色一定相同。可以发现如果只有行或只有列,那么每行(每列)的颜色不一定相同,而同时有行和列就必须是同一颜色。那么用行数 + + + 列数套上容斥系数就行了。
其实在这道题中,我们容易得到有至少 i i i 行相同且有至少 j j j 列相同的方案数,当我们不容易得到时,就需要使用容斥 dp 了
容斥的一些模型如下
- 所有的情况 − - − 至少有一个 + + + 至少有两个 − ⋯ = - \cdots = −⋯=一个也没有。
- 全部都有 − - − 一个也没有 = = = 至少有一个
- 至少有 k k k 个 − - − ( k + 1 k ) k + 1 \choose k (kk+1) × \times ×至少有 k + 1 k+1 k+1 个 + + + ( k + 2 k ) k + 2 \choose k (kk+2) × \times × 至少有 k + 2 k+2 k+2 ⋯ = \cdots = ⋯= 恰好有 k k k 个的方案数
- 补集转化
- min-max 容斥
- …
然后随便做几道题熟悉一下。
BZOJ 3622 (type 3)
给定两个全不相等的两个序列 a a a 和 b b b,把 a a a 中的元素和 b b b 中的元素两两配对,求 a i > b j a_i > b_j ai>bj 比 a i < b j a_i < b_j ai<bj 的配对数恰好多 k k k 的方案数。
显然所有的配对不是 a i > b j a_i > b_j ai>bj 就是 a i < b j a_i < b_j ai<bj,解一个方程可以转换成了恰好有 x x x 个配对满足 a i > b j a_i > b_j ai>bj 的方案数。
可以考虑一下第三类容斥,把问题转换成求有至少 x , x + 1 , . . . , n x, x + 1,...,n x,x+1,...,n 个配对满足 a i > b j a_i > b_j ai>bj 的方案数。
将 a a a 和 b b b 从小到大排序,设 f i , j f_{i,j} fi,j 前 a 1 ∼ a i a_1 \sim a_i a1∼ai 配对了 j j j 个满足要求的 b j b_j bj,其它不管的方案数,其实这是一个延迟转移。
f i , j = f i − 1 , j + f i − 1 , j − 1 × ( k − j + 1 ) f_{i,j} = f_{i - 1, j} + f_{i-1,j-1} \times (k - j + 1) fi,j=fi−1,j+fi−1,j−1×(k−j+1)
其中 k k k 是最大的数,满足 k < a i k < a_i k<ai。
那么 f n , x ( n − x ) ! f_{n,x} (n-x)! fn,x(n−x)! 即为至少有 j j j 个的方案数。
a n s = ∑ i = x n ( x i ) f n , i ( n − i ) ! ans = \sum_{i = x}^n {x \choose i} f_{n,i} (n-i)! ans=i=x∑n(ix)fn,i(n−i)!
ARC 115 E (type 1)
有 n n n 个位置,每个位置上的数字不能大于 a i a_i ai,求相邻的数都不相同的序列有多少个。
1 ≤ n ≤ 5 × 1 0 5 , 1 ≤ a i ≤ 1 0 9 1 \leq n \leq 5 \times 10^5, 1 \leq a_i \leq 10^9 1≤n≤5×105,1≤ai≤109。
所有的情况 − - − 至少有一个 + + + 至少有两个 − ⋯ = - \cdots = −⋯=一个也没有。
令 f i , j f_{i,j} fi,j 为将前 i i i 个元素分成 j j j 段的方案数,其中每段内都相等,段与段之间无所谓。那么答案是 f n , n − f n , n − 1 + f n , n − 2 ⋯ f_{n,n} - f_{n,n-1} + f_{n,n-2} \cdots fn,n−fn,n−1+fn,n−2⋯
f i , j = ∑ k < i f k , j − 1 × min k + 1 ≤ i a k f_{i,j} = \sum_{k <i} f_{k,j-1} \times \min_{k+1 \leq i} a_k fi,j=k<i∑fk,j−1×k+1≤iminak
但显然这个转移是 O ( n 2 ) O(n^2) O(n2),但容斥系数只与 j j j 的奇偶性有关,所以状态可以改成 f i , 0 / 1 f_{i,0/1} fi,0/1 表示前 i i i 个数分成偶数段(奇数段)的方案数。
f i , 1 = ∑ k < i f k , 0 × min k + 1 ≤ i a k f i , 0 = ∑ k < i f k , 1 × min k + 1 ≤ i a k f_{i,1} = \sum_{k <i}f_{k,0} \times \min_{k + 1 \leq i} a_k \\ f_{i,0} = \sum_{k <i} f_{k,1} \times \min_{k+1 \leq i} a_k fi,1=k<i∑fk,0×k+1≤iminakfi,0=k<i∑fk,1×k+1≤iminak
好像这个转移还是 O ( n 2 ) O(n^2) O(n2),但是可以优化了。我们用单调栈算出每个 a k a_k ak 作为最小值的区间,然后再维护一个 dp 的前缀和,加上一点点细节就可以了。

浙公网安备 33010602011771号