前言
方便自己看的…
做法
一般我们可以有一类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
y⋃z=x且
y
⋂
z
=
∅
y\bigcap z=\emptyset
y⋂z=∅
那么朴素做法就是先枚举子集,然后转移,复杂度是
3
n
3^n
3n的
然后我们发现,这其实就是一个类似卷积的过程
只不过有一些限制
就是上面的交集与并集的限制
我们可以修改一下这个限制,并用逻辑运算符代替之
y
∣
z
=
x
y|z=x
y∣z=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]=maskj∣maskk=maski∑f[j][maskj]∗cal[i−j][maskk]
这就是一个标准的FWT形式了
于是我们可以按集合内元素个数从小到大转移这个方程
每做完一层转移,我们就将其FWT一次
然后每层转移是
n
2
n
n2^n
n2n的
所以复杂度是
2
n
n
2
2^nn^2
2nn2噜
例题
loj2340 [WC2018]州区划分
在这里