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

题目描述

传送门

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

题解

xi 表i给i+1传递的糖果的数量
那么我们可以得到n个方程
xnx1=a¯a1
x1x2=a¯a2
x2x3=a¯a3

xn1xn=a¯an
那么对于方程做前缀和就能得到n个新的方程
xnxi=ij=1a¯aj
对于上面的方程进行变形,就能表示出 xi
xi=xnij=1a¯aj
我们的目标就是要最小化 ans=ni=1|xi|=ni=1(xnij=1a¯aj)
对于 xn 的取值,可以是不超过总和的任意值,显然所有的前缀和一定都在合法的范围之内。
那么我们只要让 xn 取到 xnij=1a¯aj 中的中位数即可。

代码

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#define N 1000003
#define LL long long 
using namespace std;
LL a[N],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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值