题意

N个盒子,每个盒子有a[i]块巧克力,每次操作可以将盒子中的一块巧克力左移或右移,要求移动后的每个盒子中的巧克力数量都能被k整除(无视空盒子),求最小的操作数。(1<=N<=1e6,0<=a[i]<=1e6)

思路

  • k只需考虑巧克力总数的质因子
  • 考虑每个盒子的贡献,盒子中可以保存k的整数倍(k*i)块巧克力,从左向右递推,每个盒子保留最大数目的巧克力,假设剩余的巧克力数目为x,则有两种情况,一是,x全部给后一个位置的盒子,二是,由后一个位置的盒子给他(k-x)块巧克力。而无论是哪种情况,都不会影响后一个盒子剩余巧克力的数量。
  • 分治的考虑这道题,将n个盒子视为两部分,每个部分能解决完k的整数倍(k*i)块巧克力,而两部分交换巧克力(距离为1)的最小代价就是对两部分的剩余巧克力取最小值,而任意两部分剩余的巧克力之和总为0或k
  • 读入不能用cin

代码

#include <cstdio>
#include <iostream>
#include <vector>
#include <set>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;
int a[maxn],n;
ll sum[maxn];
inline ll solve(ll k){
ll res=0;
for(int i=1;i<=n;i++){
ll x=sum[i]%k;
res+=min(x,k-x);
}
return res;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",a+i);
sum[i]=a[i]+sum[i-1];
}
ll tot=sum[n],ans=LLONG_MAX;
for(ll i=2;i*i<=tot;i++){
if(tot%i) continue;
ans=min(ans,solve(i));
while (tot%i==0) {
tot/=i;
}
}
if(tot!=1) ans=min(ans,solve(tot));
if(ans!=LLONG_MAX)cout<<ans<<endl;
else cout<<-1<<endl;
}

最新文章

  1. C#开发微信门户及应用(40)--使用微信JSAPI实现微信支付功能
  2. MySQL中有关TIMESTAMP和DATETIME的总结
  3. DbUtility v3 背后的故事
  4. C#注解属性的感想一:
  5. fzu月赛 2203 单纵大法好 二分
  6. django中自定义标签和过滤器
  7. C#读写xml文件的常用方法
  8. 怎样在EPLAN P8里创建自己想要的电气元件符号
  9. PAC(Proxy Auto Config)代理自动配置文件的编写
  10. maven管理多模块系统
  11. 使用Common.Logging+log4net规范日志管理
  12. hibernate通过判断参数动态组合Hql语句,生成基本通用查询
  13. 3分钟教你做一个iphone手机浏览器
  14. SuperMap iServer 在Linux 部署中问题总结
  15. C# 高级编程03----细节内容
  16. Notepad++ PluginManager安装常用插件
  17. anaconda 的安装
  18. 初见SDN
  19. app软件遵循的规范
  20. linux中date命令显示

热门文章

  1. 1473. [Ioi2000]Post加强版 n log^2 n做法
  2. [算法模版]AC自动机
  3. Guava---缓存之LRU算法
  4. spring boot 启动遇到报错:Failed to configure a DataSource
  5. 【转帖】Linux文件夹对比并提取的差分文件技巧-rsync的妙用
  6. Java笔记_web.xml文件
  7. Codeforces Round #588 (Div. 1)
  8. SQL系列(三)—— 注释(comment)
  9. ad域的那些事儿
  10. 修改dedecms 一些配置cfg_softname,cfg_soft_enname,cfg_soft_devteam