您的位置:首页 > 其它

bzoj 1045: [HAOI2008] 糖果传递 (数学相关)

2017-05-02 10:34 218 查看

题目描述

传送门

题目大意: 有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为1。求使所有人获得均等糖果的最小代价。

题解

设xi表i给i+1传递的糖果的数量

那么我们可以得到n个方程

xn−x1=a¯−a1

x1−x2=a¯−a2

x2−x3=a¯−a3



xn−1−xn=a¯−an

那么对于方程做前缀和就能得到n个新的方程

xn−xi=∑ij=1a¯−aj

对于上面的方程进行变形,就能表示出xi

xi=xn−∑ij=1a¯−aj

我们的目标就是要最小化ans=∑ni=1|xi|=∑ni=1(xn−∑ij=1a¯−aj)

对于xn的取值,可以是不超过总和的任意值,显然所有的前缀和一定都在合法的范围之内。

那么我们只要让xn取到xn−∑ij=1a¯−aj中的中位数即可。

代码

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#define N 1000003
#define LL long long
using namespace std;
LL a
,sum;
int n;
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%lld",&a[i]),sum+=a[i];
sum/=n;
a[1]=sum-a[1];
for (int i=2;i<=n;i++){
int t=sum-a[i];
a[i]=a[i-1]+t;
}
sort(a+1,a+n+1);
LL t=a[n/2+1]; LL ans=0;
for (int i=1;i<=n;i++) ans+=abs(t-a[i]);
printf("%lld\n",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数学相关