传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3675
【题解】
当时想的时候猜了下从前往后分比较优。
后来证明了一下怎么分都一样。。可以把贡献式子拆开来分析。
这样分析完就可以得到贡献=Σ每两个块的和的积
那么我们整理可以得到贡献=Σ第i个块的和*(前面所有块的和)
那么有dp: f[i,j]表示到第i块,选择的数是a[1]...a[j]的贡献max。
那么直接dp有50分。
# include <stdio.h> # include <string.h> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 1e5 + 10, N = 210; const int mod = 1e9+7; # define RG register # define ST static int n, K, a[M]; ll s[M], f[N][M]; int pre[N][M]; inline void prt(int i, int j) { if(i == 1) return; prt(i-1, pre[i][j]); printf("%d ", pre[i][j]); } int main() { scanf("%d%d", &n, &K); for (int i=1; i<=n; ++i) scanf("%d", &a[i]), s[i] = s[i-1] + a[i]; for (int i=2; i<=K+1; ++i) for (int j=1; j<=n; ++j) { f[i][j] = -1e18; for (int k=1; k<j; ++k) { if(f[i][j] < f[i-1][k] + (s[j]-s[k])*s[k]) { f[i][j] = f[i-1][k] + (s[j]-s[k])*s[k]; pre[i][j] = k; } } } printf("%lld\n", f[K+1][n]); prt(K+1, n); return 0; }