[Codeforces Round #601 (Div. 2)]E2. Send Boxes to Alice(Hard Version)

简化版https://blog.csdn.net/qq_33831360/article/details/103170669
就是数据变大了

优化:k不是sqrt枚举,因为因子nk(个一组)结果可能不比因子k(个一组)好,所以分解质因数枚举质因子k

枚举的方法:移动到点i后,积累了had<k个礼物,那么有两种选择,把这had个后移,或把k-had个前移。
计算过程模拟的是后移,但实际上,对于这k个礼物,前一部分后移,随着had变大,后一部分前移。是有一致性的,且后部分模拟后移只是为了计算需要前移多少。


#include <iostream>
#include <cstdio>
#include <vector>
#include <cmath>
 
using namespace std;
#define int long long 
int n;
typedef long long LL;
LL a[1000003];
 
LL calc(int x) {
	LL ans = 0;
	LL had = 0;
    for (int i = 1; i <= n; i++) {
    	had = had+a[i];
		if (had > x) had %= x;
    	ans += min(had,x-had);
	}
	return ans;
}
 
main() {
	LL sum = 0;
	cin >> n;
	for (int i = 1; i <= n; i++) {
		scanf("%I64d",&a[i]);
		sum += a[i];
	}
	if (sum <= 1) {
		puts("-1");
		return 0;
	} 
	LL ans = (LL)1e18;
	for (LL i = 2; i <= sqrt(sum); i++)
		if (sum % i == 0) {
			ans = min(ans,calc(i));
			while (sum%i == 0) sum /= i;
		}
	if (sum > 1) ans = min(ans,calc(sum));
    cout << ans;
	return 0;
}
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值