二项式反演详解+例题

基本公式

g ( i ) = ∑ j = 0 i C i j f ( j ) g(i)=\sum_{j=0}^i C_i^j f(j) g(i)=j=0iCijf(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=0i(1)ij 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(1in)满足 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×(ni)!,其中 C n i C_n^i Cni表示选择满足 A i = i A_i=i Ai=i i i i,对于剩余的位置任意安排,即 ( n − i ) ! (n-i)! (ni)!

定义 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(ji)被算了 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=infj 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=in(1)ji 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=imCji fj

为什么呢?因为对于一个 f x f_x fx,如果 y ≤ x y≤x yx,那么 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=im(1)ji gj Cji

所以,只需要求出所有满足 0 ≤ i ≤ m 0≤i≤m 0im 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 n2000,吸取例 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=dpi1,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=dpi1,j1×(cntj+1)。即,在这 c n t cnt cnt个可与其配对的数中,有 j − 1 j-1 j1个数已经被占用了,不能被重复选;因此能选的数实际上只有 c n t − ( j − 1 ) = c n t − j + 1 cnt-(j-1)=cnt-j+1 cnt(j1)=cntj+1个,因此转移时应添加系数 c n t − j + 1 cnt-j+1 cntj+1

根据上述 d p dp dp的状态设计, g i = d p n , i × ( n − i ) ! g_i=dp_{n,i}×(n-i)! gi=dpn,i×(ni)! ( n − i ) ! (n-i)! (ni)!表示,对于 n − i n-i ni个没有去钦定的数,我们随便配对,显然有 ( n − i ) ! (n-i)! (ni)!种配对方式。

接下来又是二项式反演的套路:

由于 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)jiCjifj

由于满足上面的数大于下面的数的配对必须恰好为 n + k 2 \frac {n+k} 2 2n+k对,所以答案为 f n + k 2 f_{\frac {n+k} 2} f2n+k

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值