简要题意#
给定序列 {an},求有多少个子序列满足所有元素的按位与为 0。
把二进制数 ai 看作集合,即要求
∏ixai+xU
取 FMT,得
∏iF(xai)+F(xU)=∏i
考虑一个背包 fi,j 表示考虑 a1 到 ai,按位与结果为 j 的子序列数量。
有转移:
fi,j=∑k&ai=jfi−1,k+fi−1,j
两端做 FWT:
Fi,j=F(∑k&ai=jfi−1,k)+Fi−1,j=Fi−1,jGi−1,j+Fi−1,j=Fi−1,j(Gi−1,j+1)
其中 Fi,⋅ 是 fi,⋅ 的 FWT,Gi,⋅ 是 gi,⋅ 的 FWT,gi,j={1j=ai0j≠ai。
简单计算可以得到同 F1 的结果。
简要题意#
给定几个数:n,t,u,v,w 满足 值域 ≤2t。给出 n 个三元组 (ai,bi,ci),表示有 x 个 ai,y 个 bi,z 个 ci。对于每个 k∈[0,2t−1],请求出从每组选出一个数的异或和为 k 的方案数。
我们要求
ans=∏uxai+vxbi+wxci
其中 ∏ 为异或卷积。考虑进行 FWT,有
F(ans)=F(∏uxai+vxbi+wxci)=∏F(uxai+vxbi+wxci)=∏uF(xai)+vF(xbi)+wF(xci)
第二行之后及下文的 ∏ 为点积。
注意到 F(xk)=∑S(±1)xS,因此
[xk]F(ans)=∏(±u±v±w)
总共只有八种情况,对于每一个 k,算出这八种情况在乘积中各出现多少次,然后快速幂就做完了。
考虑到八种情况还是太臃肿了,我们进行一个小 trick:将 bi,ci 异或上 ai,然后令 ai=0,最终输出答案的时候再异或回来即可,故 F(xai)=F(x∅)=∑xS,所以 u 的系数恒为 1,只剩下四种情况
u+v+w,u−v+w,u+v−w,u−v−w
记他们出现的次数分别为
c1,c2,c3,c4
接下来考虑如何计算。直接算显然是不切实际的,但是我们考虑只计算 v 的系数的和 pv,则有对于最终答案的 xk 这一项,
pv=∑[xk]F(xbi)=[xk]∑F(xbi)=[xk]F(∑xbi)
对于 w 和 pw 同理,再加上 c1+c2+c3+c4=n,我们得到了三个线性无关的方程,考虑再找一个方程:
注意到 F(xbi)F(xci)=F(xbi⊕ci) 为 v,w 系数的乘积记为 pv⊕w,有
pv⊕w=[xk]F(∑xbi⊕ci)
至此四个方程集齐:
c1+c2+c3+c4=nc1−c2+c3−c4=pvc1+c2−c3−c4=pwc1−c2−c3+c4=pv⊕w
解出来之后做个快速幂,然后 IFWT 就做完了。
简要题意#
给定 n×m 权矩阵 wij∈{−∞}∪N,求从矩阵中取若干行和若干列,使得行列相交处的和最大。
n≤20,m≤106
注意到 n 很小,我们可以枚举选取的行的集合。
考虑记 Li 为第 i 行中不为 −∞ 的列的集合,记 f(S) 为选的行的集合为 S 时的最大收获,则有
f(S)=∑i∈S∑j∈LSwijLS=⋂i∈SLi
进一步转化:
f(S)=∑i∈S∑j[j∈LS]wij=∑j∑i∈S[j∈LS]wij=∑jfj(S)
其中
fj(S)={∑i∈Swij(j∈LS)0(j∉LS)
注意到 fj(S) 只在 LS 的子集内有值,所以我们尝试通过子集加/高维前缀加来生成 fj(S):
很容易发现,如果我们对 LS 的所有子集加上 ∑i∈LSwij;对于 x∈LS,让 LS∖x 的所有子集减去 wxj 即可生成 fj(S)。
对于每一个 j 我们单点加,然后一起做一次 FMT 后缀和即可。复杂度 O(n2n+nm)。
tips:遇到奇奇怪怪的集合式子如果不能直接写成卷积的形式,可以考虑化成一系列序列相加,然后尝试让每个序列都能由简单序列的 FWT/FMT 生成。
这时候就不要考虑用形式化的式子去做差分前缀和看能不能变简单了,直接考虑能不能通过少量的前缀和/后缀和/前后缀差分等操作产生序列即可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?