子集卷积

前言

方便自己看的…

做法

一般我们可以有一类dp方程
譬如 f [ x ] = ∑ f [ y ] ∗ c a l [ z ] f[x]=\sum f[y]*cal[z] f[x]=f[y]cal[z],其中 c a l [ z ] cal[z] cal[z]代表需要的代价
满足 y ⋃ z = x y\bigcup z=x yz=x y ⋂ z = ∅ y\bigcap z=\emptyset yz=
那么朴素做法就是先枚举子集,然后转移,复杂度是 3 n 3^n 3n

然后我们发现,这其实就是一个类似卷积的过程
只不过有一些限制
就是上面的交集与并集的限制
我们可以修改一下这个限制,并用逻辑运算符代替之
y ∣ z = x y|z=x yz=x ∣ y ∣ + ∣ z ∣ = ∣ x ∣ |y|+|z|=|x| y+z=x
即或运算后等于 x x x且大小相加为 x x x的大小

显然我们满足下面的限制后就可以满足上面的限制
那么可以设一类dp方程
f [ x ] [ m a s k ] f[x][mask] f[x][mask]表示集合内共有 x x x个元素, m a s k mask mask表示这 x x x个元素分别是什么
那么
f [ i ] [ m a s k i ] = ∑ m a s k j ∣ m a s k k = m a s k i f [ j ] [ m a s k j ] ∗ c a l [ i − j ] [ m a s k k ] f[i][mask_i]=\sum_{mask_j|mask_k=mask_i} f[j][mask_j]*cal[i-j][mask_k] f[i][maski]=maskjmaskk=maskif[j][maskj]cal[ij][maskk]
这就是一个标准的FWT形式了
于是我们可以按集合内元素个数从小到大转移这个方程

每做完一层转移,我们就将其FWT一次
然后每层转移是 n 2 n n2^n n2n
所以复杂度是 2 n n 2 2^nn^2 2nn2

例题

loj2340 [WC2018]州区划分
在这里

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值