设 fx,0,i 表示 x 子树中,所有包含 x 且异或和为 i 的连通块数量,fx,1,i 表示 x 子树中异或和为 i 的连通块数量。显然,有公式
fx,1,i=fx,0,i+∑y∈subtreexfy,1,i
现在考虑 fx,0,i 的转移。假如我们要合并 x 与某个儿子 y 的DP数组,则显然有公式
fx,0,i=∑jxork=if′x,0,j×(fy,0,k+[k=0])
其中 f′ 是老的 f 数组。
发现这是异或卷积形式,可以FWT优化。
但是我们发现,因为DP过程中全程要么在卷积,要么在做加法,对FWT后的数组作也是一样的。因此我们重新修改定义,将 f 数组全数修改为FWT后的数组。又因为 z0 这个函数在FWT后会得到 m∑i=0zi,因此转移式变更为
fx,1,i=fx,0,i+∑y∈subtreexfy,1,i
fx,0,i=f′x,0,j×(fy,0,k+1)
直接硬DP,单次复杂度 O(nm)。
现在考虑轻重链剖分。设 g 表示仅考虑轻儿子时的答案。若只考虑 x 的一个重儿子 y,则有
fx,0=gx,0×(fy,0+1)=gx,0fy,0+gx,0
fx,1=fx,0+gx,1+fy,1=gx,0fy,0+gx,0+gx,1+fy,1
当然,这里的所有东西都是函数,连上面的 1 都不例外,指的是元素全为 1 的函数。
同时,要留心一点常规 g 的转移:
gx,0=FWT(zax)∏y∈lightsonx(fy,0+1)
gx,1=∑y∈lightsonxfy,1
需要注意的是,叶节点的 g 数组应直接是其 f 数组,故对于叶子节点,有 gx,0=gy,0=FWT(zax)。
我们可以列出转移矩阵来:
⎡⎢⎣fy,0fy,11⎤⎥⎦⎡⎢⎣gx,0gx,00010gx,0gx,0+gx,11⎤⎥⎦=⎡⎢⎣fx,0fx,11⎤⎥⎦
3×3 矩阵就有着 33 的常数,不好玩。但是,当我们计算两个上述矩阵的积后
⎡⎢⎣a1b10010c1d11⎤⎥⎦⎡⎢⎣a2b20010c2d21⎤⎥⎦=⎡⎢⎣a1a2b1+a1b20010a2c1+c2b2c1+d1+d21⎤⎥⎦
发现矩阵的积不会影响其余位置的取值。
因此我们考虑只维护 a,b,c,d 四个位置的值,即可压缩矩阵为 2×2。
于是现在的转移矩阵就压缩为
[a1b1c1d1][a2b2c2d2]=[a1a2b1+a1b2a2c1+c2b2c1+d1+d2]
同时,其存在单位元
[1000]
我们同时还要支持从链顶父亲的 g 数组中删掉一个 f 数组的操作。这样就需要支持除法。但是你不能保证FWT不会出现零。但我们可以维护每个位置的非零数之积是什么,再维护每个位置出现了多少零,这样分开处理,即可支持除法。
代码先咕着
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?