SOSDP
严肃学习
考虑例题:对于每个 \(i \in [0,2^n-1]\),求 \(\displaystyle \sum_{j\in i} a_j\)。
考虑朴素地枚举子集求解,可以做到 \(O(3^n)\)。
for (ll mas = S; mas; mas = (mas - 1) & S) {
// do something
}
考虑分治,现在求 \([0,2^n-1]\) 的答案,分裂成 \([2^{n-1},2^n-1]\) 和 \([0,2^{n-1}-1]\),后者继续递归下去。考虑前者的答案,你发现所有数减掉一个 \(2^{n-1}\) 后,就可以和后者的数一一对应,那么容易计算贡献。
然后可以写成循环形式,核心代码三行:
for (ll i = 0; i < n; ++ i ) {
for (ll mas = 0; mas < (1ll << n); ++ mas ) {
if (mas >> i & 1)
f[mas] = merge(f[mas], f[mas - (1ll << i)]);
}
}
浙公网安备 33010602011771号