基本公式
若
g
(
i
)
=
∑
j
=
0
i
C
i
j
f
(
j
)
g(i)=\sum_{j=0}^i C_i^j f(j)
g(i)=j=0∑iCijf(j)
则
f
(
i
)
=
∑
j
=
0
i
(
−
1
)
i
−
j
C
i
j
f
(
j
)
f(i)=\sum_{j=0}^i (-1)^{i-j}\ C_{i}^j f(j)
f(i)=j=0∑i(−1)i−j Cijf(j)
是的,二项式反演本身就是这么简单,本质上只是一个容斥。
关键在于,我们要如何利用好这个重要的式子。往往,我们都想要求出 f f f但只会快速求出 g g g,此时我们会使用二项式反演,通过 g g g逆向得到我们想要的 f f f。
例1 欧拉错排
请求出对于所有长度为 n n n的排列 A A A,满足其中不存在任何一个位置 i ( 1 ≤ i ≤ n ) i(1≤i≤n) i(1≤i≤n)满足 A i = i A_i=i Ai=i的排列的数量。
定义 g i g_i gi表示钦定了 i i i个位置使得 A i = i A_i=i Ai=i的排列数量。显然 g i = C n i × ( n − i ) ! g_i=C_n^i×(n-i)! gi=Cni×(n−i)!,其中 C n i C_n^i Cni表示选择满足 A i = i A_i=i Ai=i的 i i i,对于剩余的位置任意安排,即 ( n − i ) ! (n-i)! (n−i)!。
定义 f i f_i fi表示恰好有 i i i个位置使得 A i = i A_i=i Ai=i的排列数量。可以发现,对于一个 g i g_i gi, f j ( j ≥ i ) f_j(j≥i) fj(j≥i)被算了 C j i C_j^i Cji次。即 g i = ∑ j = i n f j C j i g_i=\sum_{j=i}^n f_j\ C_j^i gi=j=i∑nfj Cji
通过二项式反演可得 f i = ∑ j = i n ( − 1 ) j − i f j C j i f_i=\sum_{j=i}^n (-1)^{j-i}\ f_j\ C_j^i fi=j=i∑n(−1)j−i fj Cji
答案为 f 0 f_0 f0。时间复杂度 O ( n ) O(n) O(n)。
例2 [NOI Online #2 T3]游戏
考虑做一个转化。
假设 g i g_i gi表示钦定选了 i i i对有祖先关系的方案数, f i f_i fi表示恰好存在 i i i对有祖先关系的答案。可以发现, g i = ∑ j = i m C j i f j g_i=\sum_{j=i}^m C_{j}^i\ f_j gi=j=i∑mCji fj
为什么呢?因为对于一个 f x f_x fx,如果 y ≤ x y≤x y≤x,那么 g y g_y gy就算了 f x C x y f_x\ C_{x}^y fx Cxy次,所以得到了上面那个式子。
通过二项式反演,可以得到 f i = ∑ j = i m ( − 1 ) j − i g j C j i f_i=\sum_{j=i}^m (-1)^{j-i}\ g_j\ C_{j}^i fi=j=i∑m(−1)j−i gj Cji
所以,只需要求出所有满足 0 ≤ i ≤ m 0≤i≤m 0≤i≤m的 g i g_i gi即可求出每个答案。如何求出这个值呢?我们考虑使用树上背包。
d p i , j dp_{i,j} dpi,j表示在以 i i i为根的子树中,钦定了 j j j对有祖先关系的对(即在这个子树内至少有 j j j对满足要求的)的方案数。每次我们将 i i i与其子树中的一个节点配对,将这个子树的各种状态与 i i i的状态合并即可。
更详细地说,
①对于合并,将
d
p
i
,
j
dp_{i,j}
dpi,j与
d
p
s
o
n
,
k
dp_{son,k}
dpson,k(
s
o
n
son
son为
i
i
i的儿子节点之一)合并成
d
p
i
,
j
+
k
dp_{i,j+k}
dpi,j+k,系数为
1
1
1;
②如果我们想要让
i
i
i号节点参与这个配对,那么
(1)如果
a
i
=
0
a_i=0
ai=0,那么一定是
0
0
0与
1
1
1配对;即将
d
p
i
,
j
dp_{i,j}
dpi,j与
d
p
s
o
n
,
k
dp_{son,k}
dpson,k合并成
d
p
i
,
j
+
k
+
1
dp_{i,j+k+1}
dpi,j+k+1,注意这里系数是以
s
o
n
son
son为根的子树中点权为
1
1
1的点数。
(2)
a
i
=
1
a_i=1
ai=1同理。
注意,我们每次合并的大小是看到这个孩子之前的 s i z e size size 与这个孩子节点的 s i z e size size,单次合并的复杂度是这两个值的乘积。
这个复杂度乍一看是 O ( n 3 ) O(n^3) O(n3)的,实际上是 O ( n 2 ) O(n^2) O(n2)的;因为,任何两个节点当且仅当会在它们的 L C A LCA LCA处算一次贡献。
总时间复杂度 O ( n 2 ) O(n^2) O(n2)。
例3 [Luogu P4859]已经没有什么好害怕的了
根据前两题的经验,我们先尝试去选择一个比较容易“钦定”的东西,然后再二项式反演乱搞。
令 g i g_i gi表示钦定了 i i i对满足上面的数大于下面的数的情况, f i f_i fi表示恰好存在 i i i对满足上面的数大于下面的数的情况。 g i g_i gi如何计算呢?看到数据范围为 n ≤ 2000 n≤2000 n≤2000,吸取例 2 2 2的经验,我们考虑二维 d p dp dp。由于这个 d p dp dp的一个整体决策必须满足每个 b b b中的数恰好被选 1 1 1次,而对于某些配对我们又钦定了条件(上面的数大于下面的数),所以我们套路性的地先对两个数组排序。
状态设计: d p i , j : dp_{i,j}: dpi,j: 看到了 A A A中的第 i i i个数,完成了 j j j次钦定;且 A A A中在区间 [ 1 , i ] [1,i] [1,i]的这些数都已经与 B B B中不同的数进行了配对。
状态转移:
①不为
A
i
A_i
Ai钦定一个比
A
i
A_i
Ai小的
B
j
B_j
Bj。此时
d
p
i
,
j
=
d
p
i
−
1
,
j
dp_{i,j}=dp_{i-1,j}
dpi,j=dpi−1,j;
②为
A
i
A_i
Ai钦定一个比
A
i
A_i
Ai小的
B
j
B_j
Bj。假设此时
B
B
B中比
A
i
A_i
Ai小的数有
c
n
t
cnt
cnt个,那么
d
p
i
,
j
=
d
p
i
−
1
,
j
−
1
×
(
c
n
t
−
j
+
1
)
dp_{i,j}=dp_{i-1,j-1}×(cnt-j+1)
dpi,j=dpi−1,j−1×(cnt−j+1)。即,在这
c
n
t
cnt
cnt个可与其配对的数中,有
j
−
1
j-1
j−1个数已经被占用了,不能被重复选;因此能选的数实际上只有
c
n
t
−
(
j
−
1
)
=
c
n
t
−
j
+
1
cnt-(j-1)=cnt-j+1
cnt−(j−1)=cnt−j+1个,因此转移时应添加系数
c
n
t
−
j
+
1
cnt-j+1
cnt−j+1。
根据上述 d p dp dp的状态设计, g i = d p n , i × ( n − i ) ! g_i=dp_{n,i}×(n-i)! gi=dpn,i×(n−i)!。 ( n − i ) ! (n-i)! (n−i)!表示,对于 n − i n-i n−i个没有去钦定的数,我们随便配对,显然有 ( n − i ) ! (n-i)! (n−i)!种配对方式。
接下来又是二项式反演的套路:
由于
g
i
=
∑
j
=
i
n
C
j
i
f
j
g_i=\sum_{j=i}^n C_j^i f_j
gi=∑j=inCjifj
所以
f
i
=
∑
j
=
i
n
(
−
1
)
j
−
i
C
j
i
f
j
f_i=\sum_{j=i}^n (-1)^{j-i} C_j^i f_j
fi=∑j=in(−1)j−iCjifj
由于满足上面的数大于下面的数的配对必须恰好为 n + k 2 \frac {n+k} 2 2n+k对,所以答案为 f n + k 2 f_{\frac {n+k} 2} f2n+k。