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; 
} 
posted @ 2018-09-25 20:33  zzzzx  阅读(259)  评论(2编辑  收藏  举报