AGC027 B - Garbage Collector 枚举/贪心
[TOC]
#题目链接
AGC027 B - Garbage Collector
#题解
对于一组选取组的最优方案为,走到一点,然后顺着路径往回取点
设选取点坐标升序为{a,b,c,d}
那么消耗为$d+(d - c) + 4* (d - c) + 9 * (c - d) + 16 * (b - a) + a * 25$
化简后为$5d + 5c + 7b - 9a$,那个对于这组k的最优解显然是让最远的点系数最小
考虑把序列划分为n / k组,枚举这个k计算,那么复杂度是调和级数的
#代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#define gc getchar()
#define pc putchar
#define int long long
inline int read() {
int x = 0,f = 1;
char c = gc;
while(c < '0' || c > '9') {if(c == '-')f = -1; char c = getchar();}
while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = getchar();
return x * f;
}
void print(long long x) {
if(x < 0) {
pc('-');
x = -x;
}
if(x >= 10) print(x / 10);
pc(x % 10 + '0');
}
const int maxn = 500007;
#define LL long long
LL ans;
LL sum[maxn],a[maxn];
main() {
LL n = read(), x = read();
for(int i = 1;i <= n;++ i) a[i] = read(),sum[i] = sum[i - 1] + a[i],ans += 1ll * 5 * a[i] + 2ll * x;
for(int k = 1;k < n;++ k) {
LL tmp = k * x;
for(int nxj,j = n,cnt = 1;j > 0;j = nxj,cnt ++) {
nxj = std::max(j - k,0ll);
LL s = sum[j] - sum[nxj];
tmp += std::max(5ll,cnt * 2ll + 1ll) * s;
if(tmp > ans) break;
}
ans = std::min(ans,tmp);
}
print(ans + 1ll * n * x); pc('\n');
return 0;
}