SOS DP
learn from blog of 海边拾贝的言
definition
sos: sum over subsets
target:
F
(
m
a
s
k
)
=
∑
i
∈
m
a
s
k
A
(
i
)
F(mask) = \sum_{i \in mask} A(i)
F(mask)=∑i∈maskA(i)
linked to FWT (need a complement), fellow are definition of FWT
F
W
T
o
r
FWT\ or
FWT or :
F
W
T
(
k
)
=
∑
i
o
r
j
=
k
A
(
i
)
∗
B
(
j
)
FWT(k) = \sum_{i\ or\ j = k} A(i) * B(j)
FWT(k)=∑i or j=kA(i)∗B(j)
F
W
T
a
n
d
FWT\ and
FWT and :
F
W
T
(
k
)
=
∑
i
a
n
d
j
=
k
A
(
i
)
∗
B
(
j
)
FWT(k) = \sum_{i\ and\ j = k} A(i) * B(j)
FWT(k)=∑i and j=kA(i)∗B(j)
F
W
T
x
o
r
FWT\ xor
FWT xor :
F
W
T
(
k
)
=
∑
i
x
o
r
j
=
k
A
(
i
)
∗
B
(
j
)
FWT(k) = \sum_{i\ xor\ j = k} A(i) * B(j)
FWT(k)=∑i xor j=kA(i)∗B(j)
you can ignore FWT, because I don’t understand well and in this blog, it will not appear again.
solution
One obvious way to solve this is brute force, whose time complexity is O ( n 4 ) O(n^4) O(n4).
for i = 1 to mask
for j = 1 to mask
if i in j
F[j] += A[i]
It’s obvious that for a mask, we iterate all range is low efficient.
A method to imporve is to iterate the subset of mask.
for i = 1 to mask
for j = i; j > 0; j = (j - 1) & i
F[i] += A[j];
Time complexity = ∑ i 2 i c o n t a i n s 1 = O ( n 3 ) = \sum_{i} 2^{i\ contains\ 1} = O(n^3) =∑i2i contains 1=O(n3)
sos dp
d
p
[
m
a
s
k
]
[
i
]
dp[mask][i]
dp[mask][i] present the sum of subsets of mask that the former
i
i
i index has been fixed, and the value of left index can be changed so here the subsets mean the subset of latter.
d
p
[
m
a
s
k
]
[
i
]
=
{
d
p
[
m
a
s
k
]
[
i
−
1
]
,
(
m
a
s
k
&
(
2
i
)
=
=
0
)
d
p
[
m
a
s
k
]
[
i
−
1
]
+
d
p
[
m
a
s
k
⨁
2
i
]
[
i
−
1
]
,
(
m
a
s
k
&
(
2
i
)
=
=
1
)
dp[mask][i] = \left\{\begin{matrix} dp[mask][i - 1],& (mask\ \& (2^i) == 0)\\ dp[mask][i - 1] + dp[mask \bigoplus 2^i][i - 1],& (mask\ \& (2^i) == 1) \end{matrix}\right.
dp[mask][i]={dp[mask][i−1],dp[mask][i−1]+dp[mask⨁2i][i−1],(mask &(2i)==0)(mask &(2i)==1)

code:
for i = 1 to N
for j = 0 to log(N)
if (i & (2^j))
dp[i][j] = dp[i][j - 1] + dp[i - (2^j)][j - 1];
else
dp[i][j] = dp[i][j - 1];
d
p
[
i
]
[
−
1
]
=
A
[
i
]
dp[i][-1] = A[i]
dp[i][−1]=A[i]
The below is dp of
i
∈
m
a
s
k
i \in mask
i∈mask, and the fellow if dp of
m
a
s
k
∈
i
mask \in i
mask∈i.
d
p
[
m
a
s
k
]
[
i
]
=
{
d
p
[
m
a
s
k
]
[
i
−
1
]
+
d
p
[
m
a
s
k
⨁
2
i
]
[
i
−
1
]
,
(
m
a
s
k
&
(
2
i
)
=
=
0
)
d
p
[
m
a
s
k
]
[
i
−
1
]
,
(
m
a
s
k
&
(
2
i
)
=
=
1
)
dp[mask][i] = \left\{\begin{matrix} dp[mask][i - 1] + dp[mask \bigoplus 2^i][i - 1],& (mask\ \& (2^i) == 0)\\ dp[mask][i - 1],& (mask\ \& (2^i) == 1) \end{matrix}\right.
dp[mask][i]={dp[mask][i−1]+dp[mask⨁2i][i−1],dp[mask][i−1],(mask &(2i)==0)(mask &(2i)==1)
code:
for i = 1 to N
for j = 0 to log(N)
if (i & (2^i))
dp[i][j] = dp[i][j - 1];
else
dp[i][j] = dp[i][j - 1] + dp[i + (2^j)][j - 1];
The difference of
o
r
or
or、
a
n
d
and
and can be thought of bits.
When
i
∈
m
a
s
k
i \in mask
i∈mask, the bit 1 of mask can change to 0 or 1, 0 of mask still remain 0, which is equivalent to
b
i
t
(
!
i
o
r
m
a
s
k
)
=
1
bit(!i\ or\ mask) = 1
bit(!i or mask)=1;
When
m
a
s
k
∈
i
mask \in i
mask∈i, the bit 1 of
m
a
s
k
mask
mask still remain 1, 1 of mask can change to 0 or 1, which is equivalent to
b
i
t
(
i
o
r
!
m
a
s
k
)
=
1
bit(i\ or\ !mask) = 1
bit(i or !mask)=1.

856

被折叠的 条评论
为什么被折叠?



