高维前缀和~~
1.首先求某个二进制状态下所有他的超集的和是多少~
for(int i = 0; i< 3 ;++i){
for(int j = 0; j<8 ;++j)
if( !(j&(1<<(i))) ) dp[j] += dp[j|(1<<(i))];
大体意思就是对于某个位置 i 来说~如果存在某个状态 j 下他的 i 位不存在,那么这个状态就一定存在他的一个超集 (j |(1<<i))这样的话就使dp[j]+=dp[j|(1<<i)]就好了。
这里有个模拟,让你更方便了解过程:
#include<bits/stdc++.h>
using namespace std;
int dp[10];
vector<int>G[10];
void trans(int x) {
int a = x % 2; x /= 2;
int b = x % 2; x /= 2;
int c = x % 2; x /= 2;
cout << c << b << a ;
}
void print(int x) {
for (int s = 0; s < G[x].size(); s++) {
trans(G[x][s]); cout << " ";
}
}
int main() {
for (int s = 0; s < 8; s++) {
G[s].push_back(s);
}
memset(dp, -1, sizeof(dp));
for (int i = 0; i < 3; ++i) {
cout << i << endl;
for (int j = 0; j < 8; ++j) {
if (!(j&(1 << (i))))
{
int v = (j | (1 << (i)));
trans(j); cout << ":"; print(j); cout << endl;
trans(v); cout << ":"; print(v); cout << endl;
for (int s = 0; s < G[v].size(); s++) {
G[j].push_back(G[v][s]);
}
dp[j] += dp[j | (1 << (i))];
cout << endl;
}
}
}
for (int s = 0; s < 8; s++) {
trans(s); cout << ":"; print(s); cout << endl;
}
return 0;
}
2.求某个二进制状态下所有他的子集的和是多少
for(int j=0;j<n;j++)
for(int i=0;i<1<<n;i++)
if(i&(1<<j)) dp[i]+=dp[i^(1<<j)];
可以把上一个模拟代码稍微改改就能用了。