问题引入:
现有
a
[
i
]
(
0
<
=
i
<
2
n
)
a[i](0<=i<2^n)
a[i](0<=i<2n)
对于每一
i
i
i,求
∑
j
∈
i
a
[
j
]
\sum_{j∈i}a[j]
∑j∈ia[j]
这里的
∈
∈
∈指二进制状态下的被包含。
暴力解决问题:
即暴力枚举子集求和。
复杂度计算:
∑ i = 0 n C n i ∗ 2 i \sum_{i=0}^nC_{n}^i*2^i ∑i=0nCni∗2i
= ∑ i = 0 n C n i ∗ 2 i ∗ 1 n − i =\sum_{i=0}^nC_{n}^i*2^i*1^{n-i} =∑i=0nCni∗2i∗1n−i
= ( 1 + 2 ) n =(1+2)^n =(1+2)n
动态规划:
考虑对于一个 i i i,枚举把一个0变成1,转移上去。
但是这样显然会有重。
比如说
i
=
0
i=0
i=0
第一轮加上
2
0
2^0
20,第二轮加上了
2
1
2^1
21
也可以第一轮加上 2 1 2^1 21,第二轮加上 2 0 2^0 20
这样就会重复。
那么考虑使增加的1的位置递增的。
设 f i , j f_{i,j} fi,j表示到 i i i了,上一次增加的1是第 j j j位上的。
那么枚举 k ( ( k > = j ) a n d ( i 的 第 k 位 是 0 ) ) k((k>=j)~and~(i的第k位是0)) k((k>=j) and (i的第k位是0)), f ( i ∣ 2 k , k ) + = f ( i , j ) f(i|2^k,k)+=f(i,j) f(i∣2k,k)+=f(i,j)
这样的复杂度是 O ( 2 n ∗ n 2 ) O(2^n*n^2) O(2n∗n2)
对于上面的式子可以前缀和优化:
即
f
(
i
,
j
)
+
=
f
(
i
,
j
−
1
)
,
f
(
i
∣
2
j
,
j
)
+
=
f
(
i
,
j
)
(
i
的
第
j
位
是
0
)
f(i,j)+=f(i,j-1),f(i|2^j,j)+=f(i,j)(i的第j位是0)
f(i,j)+=f(i,j−1),f(i∣2j,j)+=f(i,j)(i的第j位是0)
复杂度 O ( 2 n ∗ n ) O(2^n*n) O(2n∗n)
正题:
把上述问题看作一个n维空间,每一维坐标的范围是 [ 0..1 ] [0..1] [0..1],求前缀和。
考虑二维暴力是怎么做的(不差分)?
先一行一行的扫描,记录下来和,然后再一列一列的扫描。
高维同理,就是一维一维的扫描。
下面给出代码实现:
fo(j, 0, N - 1) fo(i, 0, (1 << N) - 1)
if(i >> j & 1) a[i] += a[i ^ (1 << j)];
复杂度 O ( 2 n ∗ n ) O(2^n*n) O(2n∗n)