高维前缀和学习小记

问题引入:

现有 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] jia[j]
这里的 ∈ ∈ 指二进制状态下的被包含。

暴力解决问题:

即暴力枚举子集求和。
复杂度计算:

∑ i = 0 n C n i ∗ 2 i \sum_{i=0}^nC_{n}^i*2^i i=0nCni2i

= ∑ i = 0 n C n i ∗ 2 i ∗ 1 n − i =\sum_{i=0}^nC_{n}^i*2^i*1^{n-i} =i=0nCni2i1ni

= ( 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 (ik0)) f ( i ∣ 2 k , k ) + = f ( i , j ) f(i|2^k,k)+=f(i,j) f(i2k,k)+=f(i,j)

这样的复杂度是 O ( 2 n ∗ n 2 ) O(2^n*n^2) O(2nn2)

对于上面的式子可以前缀和优化:
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,j1),f(i2j,j)+=f(i,j)(ij0)

复杂度 O ( 2 n ∗ n ) O(2^n*n) O(2nn)

正题:

把上述问题看作一个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(2nn)

你可能感兴趣的:(动态规划,模版)