• [学习笔记]子集卷积


    前置知识

    • FMT:对于两个下标在 ([0,2^n)) 的数组 (f)(g),求:

    • [h_i=sum_{j ext{ or }k=i}f_jg_k ]

    • 可以做到 (O(2^nn))

    • 限于博主水平,这里不放该前置算法的流程,请自行百度

    引入

    • 对于两个下标在 ([0,2^n)) 的数组 (f)(g),求:

    • [h_i=sum_{j ext{ and }k=varnothing,j ext{ or }k=i}f_jh_k ]

    • (j,k) 的条件即为集合 (j)(k) 恰好拼成集合 (i)

    • (h)(f)(g)子集卷积

    • 可以做到 (O(2^nn^2)) 的复杂度

    算法流程

    • 下面用 (|i|) 表示 (popcount(i)),即 (i) 二进制下 (1) 的个数

    • 注意到 (j ext{ and }k=varnothing) 时必有 (|j|+|k|=|j ext{ or }k|)

    • 故引入占位多项式

    • [F_{i,j}=egin{cases}f_j & |j|=i\0 & |j| e iend{cases} ]

    • (H_{i,j}) 时,可以枚举拼成 (j) 的两个集合大小 (i_1)(i_2),我们有:

    • [H_{i,j}=sum_{i_1+i_2=i}sum_{a ext{ or }b}F_{i_1,a}G_{i_2,b} ]

    • 也就是:

    • [H_i=sum_{i_1+i_2=i}F_{i_1}igotimes G_{i_2} ]

    • (igotimes) 为或卷积

    • (H_i) 中可能会有 (1) 的个数小于 (i) 的项为 (0),但这并不重要

    • 对于每个 (0le ile n),把 (F_i)(G_i) 做一遍 FMT,作一遍上式之后得到 (H) 再 IFMT 回来即可得到 (h)

    • (O(2^nn^2))

    拓展

    • 观察这个式子

    • [H_i=sum_{i_1+i_2=i}F_{i_1}igotimes G_{i_2} ]

    • 发现 (sum_{i_1+i_2=i}) 就是我们常见的多项式卷积!

    • 于是把 (F) 视为一个 (n) 次多项式(每个项的系数都是一个集合幂级数,即 (F_i)

    • 也就是占位多项式,我们就可以进行求逆甚至 (ln)(exp)

    • 求逆可直接使用 (g_i=frac{1-sum_{j=0}^{i-1}g_jf_{i-j}}{f_0}) 进行递推

    • 对于 (ln) 我们有 (g=ln f=frac{f'}f)

    • 对于 (exp) 我们有 (g=exp f)(g'=gf'),可以递推出 (g) 的每一项

    LOJ#3165「CEOI2019」游乐园

    • 给定一个 (n) 节点 (m) 边的有向图,可以将部分边反向,求使得原图无环的所有方案下,翻转的边数之和,(nle 18)

    • 首先无环图所有边反向之后还是无环图,这样的两个合法图一一对应并且翻转的边数之和为 (m),故答案为方案数乘 (frac m2)

    • (f_S) 表示点集 (S) 无环的方案数

    • 一个图无环当且仅当这个图能够拓扑排序,严谨地说就是每次删掉图中入度为 (0) 的点集可以删完所有点

    • 考虑枚举 (0) 入度的点集(必须为独立集),强制这个点集向外的边只能连出不能连入

    • 这样无法保证外面的点入度不为 (0),考虑容斥掉有多出 (0) 入度点的情况

    • 省略推导过程,

    • [f_S=sum_{Tsubseteq S,T ext{ is an independent set}}(-1)^{|T|-1}f_{S-T} ]

    • 设集合幂级数 (g=sum_{S ext{ is an independent set}}(-1)^{|S|-1}x^S),对 (g) 的占位多项式每一项求 FMT 之后就能推出 (f) 占位多项式的每一项的 FMT

    • (O(2^nn^2))

    • 也可以从另一个角度理解:上式相当于 (f=figotimes g+1),也就是 (f=frac1{1-g}),上面推出 (f) 的某一项,本质上是在进行一个求逆的过程

    • (此处为后话)

    • (1-g) 的第 (T) 项,若 (T) 为独立集(包括空集)则为 ((-1)^{|T|}),否则为 (0)

    • 对于常数项为 (1) 的集合幂级数 (A),有个性质是 (A^k)(子集卷积意义下)的每一项都是关于 (k) 的多项式(可以根据空集在 (k) 次中被选出的次数进行证明)

    • 故我们得出一个结论:给图用 (k) 种颜色染色(边两端的点颜色不同)的方案数 (f(k)) 是一个关于 (k) 的多项式,给图定向成为 DAG 的方案数为 ((-1)^nf(-1))

    LOJ#154 集合划分计数

    • 给定一个集合幂级数 (f),求把全集划分成不超过 (k) 个集合(集合之间无序),这些集合在 (f) 中对应项的乘积之和

    • 这是一个不完整的 (exp)

    • [g=sum_{i=0}^kfrac{f^i}{i!} ]

    • 还是考虑和 (exp) 一样求导:

    • [g'=sum_{i=1}^kfrac{if^{i-1}f'}{i!}=f'sum_{i=0}^{k-1}frac{f^i}{i!} ]

    • 于是我们有:

    • [g'=f'(g-frac{f^k}{k!}) ]

    • 也可以从小到大推 (g) 占位多项式的每一项

    • 参考 EI 的博客

  • 相关阅读:
    数据结构与算法之PHP排序算法(快速排序)
    ThinkPHP5.0源码学习之注册错误和异常处理机制
    ThinkPHP5.0源码学习之注册自动加载
    C高级 跨平台协程库
    C中级 MariaDB Connector/C API 编程教程
    C高级 框架开发中红黑树结构
    c json实战引擎四 , 最后❤跳跃
    C基础 万能动态数组
    C基础 内存统一入口
    C基础 一个可以改变linux的函数getch
  • 原文地址:https://www.cnblogs.com/xyz32768/p/12953188.html
Copyright © 2020-2023  润新知