问题引入:
现有a[i](0<=i<2n)a[i](0<=i<2^n)a[i](0<=i<2n)
对于每一iii,求∑j∈ia[j]\sum_{j∈i}a[j]∑j∈ia[j]
这里的∈∈∈指二进制状态下的被包含。
暴力解决问题:
即暴力枚举子集求和。
复杂度计算:
∑i=0nCni∗2i\sum_{i=0}^nC_{n}^i*2^i∑i=0nCni∗2i
=∑i=0nCni∗2i∗1n−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
动态规划:
考虑对于一个iii,枚举把一个0变成1,转移上去。
但是这样显然会有重。
比如说i=0i=0i=0
第一轮加上202^020,第二轮加上了212^121
也可以第一轮加上212^121,第二轮加上202^020
这样就会重复。
那么考虑使增加的1的位置递增的。
设fi,jf_{i,j}fi,j表示到iii了,上一次增加的1是第jjj位上的。
那么枚举k((k>=j) and (i的第k位是0))k((k>=j)~and~(i的第k位是0))k((k>=j) and (i的第k位是0)),f(i∣2k,k)+=f(i,j)f(i|2^k,k)+=f(i,j)f(i∣2k,k)+=f(i,j)
这样的复杂度是O(2n∗n2)O(2^n*n^2)O(2n∗n2)
对于上面的式子可以前缀和优化:
即f(i,j)+=f(i,j−1),f(i∣2j,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(2n∗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(2n∗n)O(2^n*n)O(2n∗n)