高维前缀和

这东西好像可以说是 sos dp,我也不太懂。

引入

对于 \(i\)\(\sum_{j \subset i} a_j\)

  1. 直接枚举子集 \(O(n3^n)\),直接爆炸了。
  2. sos dp,\(O(n2^n)\),一下就好了。

代码:

for(int j = 0; j < n; j ++) {
	for(int i = 0; i < 1 << n; i ++) {
		if(i >> j & 1) f[i] += f[i ^ 1 << j];
	}
}

理解一下:其实就是对于每一层的 \(j\),来看所有的 \(i\),然后由于 \(i\) 从小到大进行遍历的,所以说 \(f_i\)\(j - 1\) 时的值,那么增加 \(j\) 这一层的变化量就到了 \(j\) 这一层的 \(f_i\)

反正总结一句话:固定维度增加这一维的变化量。

例题

arc100_e

考试题,这不是直接上个 sos dp 秒了吗?只是改成了记录最大值 + 次大值吗?

竟然是个蓝?

所以强的不是我,是板子和前人的思路。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using ull = unsigned long long;
using ai2 = array<int, 2>;
const int N = 18;
int n, a[1 << N], ans;
ai2 f[1 << N];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    cin >> n;
    for(int i = 0; i < 1 << n; i ++) cin >> a[i], f[i] = ai2{a[i], -0x3f3f3f3f};
    for(int j = 0; j < n; j ++) {
        for(int i = 0; i < 1 << n; i ++) {
            if(i >> j & 1) {
                vector<int> vec = {f[i][0], f[i][1], f[i ^ 1 << j][0], f[i ^ 1 << j][1]};
                sort(vec.begin(), vec.end(), greater<>());
                f[i] = ai2{vec[0], vec[1]};
            }
        }
    }
    for(int i = 1; i < 1 << n; i ++) {
        ans = max(ans, f[i][0] + f[i][1]);
        cout << ans << '\n';
    }
    return 0;
}
posted @ 2025-11-23 16:05  iesyo_31  阅读(0)  评论(0)    收藏  举报