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
#include
#include
#include
#include
#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);
}

你可能感兴趣的:(数论)