现有 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)