本文已参与「新人创作礼」活动,一起开启掘金创作之路。
原题地址
提交 10.41k
通过 4.81k
时间限制 1.00s
内存限制 125.00MB
题目描述
有 n 个小朋友坐成一圈,每人有 ai 个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为 1 。
输入格式
小朋友个数 n,下面 n 行 ai 。
输出格式
求使所有人获得均等糖果的最小代价。
输入输出样例
输入 #1
4
1
2
5
4
输出 #1
4
说明/提示
对于 100% 的数据 n≤106 。
思路:
设每个人原来拥有糖果数量为 Ai ,每次向右传递数量为 Xi (向左为 −Xi ),糖果平均数为 avg 。
则有
原有的−向右传出去的+左边传进来的=平均数
即
Ai−Xi+Xi+1=avg
联立方程
⎩⎨⎧A1−X1+X2A2−X2+X3⋯An−1−Xn−1+XnAn−Xn+X1=avg=avg=avg=avg
整理得
⎩⎨⎧−X1+X2−X2+X3⋯−Xn−1+XnX1−Xn=avg−A1=avg−A2=avg−An−1=avg−An
其增广矩阵
B=(Aβ)=⎣⎡−10⋮011−10001⋱00⋯⋯⋯⋯00−1000⋮1−1ave−A1ave−A2⋮ave−An−1ave−An⎦⎤
化为行最简形
⎣⎡10⋮00010000⋱00⋯⋯⋯⋯0010−1−1⋮−10(∑i=1n−1Ai)−(n−1)ave(∑i=2n−1Ai)−(n−2)ave⋮An−1−ave0⎦⎤
得方程组的解为
⎩⎨⎧X1X2Xn−1Xn=Xn+(i=1∑n−1Ai)=Xn+(i=2∑n−1Ai)⋮=Xn+An−1=Xn−(n−1)ave−(n−2)ave−ave∈R
现在要求 ∑i=1n∣Xi∣ 的最小值
观察方程组的解,发现所有项都有相同的变量 Xn ,所以构造函数
Xx=Xn+f(x)
即
f(x)=i=x∑n−1Ai−(n−x)ave
所以
i=1∑n∣Xi∣=∣Xn+f(1)∣+⋯+∣Xn+f(n)∣=i=1∑n∣Xn+f(i)∣
而 ∑i=1n∣Xn+f(i)∣ 可以看作数轴上的点 Xn 到点 −f(i),i∈[1,n] 的距离之和
那么 Xn 应取最中间的点(高中结论,函数图像为平底锅( n 为偶数)或尖底锅( n 为奇数))
于是我们只要找到 −f(i),i∈[1,n] 的中位数,把他赋值给 Xn 即可
将其代入∑i=1n∣Xn+f(i)∣ 即为本题答案
PS: f(x) 有递归求法 f(i)=f(i+1)+Ai−ave ,从后往前循环即可,不要用 f(x)=∑i=xn−1Ai−(n−x)ave ,后者会导致 TLE
AC 代码
R73269788 记录详情
编程语言 C++20
代码长度 494B
用时 2.34s
内存 8.05MB
#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=(a);i<=(b);++i)
#define ROF(i,a,b) for(int i=(a);i>=(b);--i)
#define ll long long
using namespace std;
const int N = 1e6+1;
int n,a[N],f[N];
ll ave=0,ans=0,Xn;
int main(){
cin>>n;
FOR(i,1,n){
cin>>a[i];
ave+=a[i];
}
ave/=n;
f[n]=0;
ROF(i,n-1,1)
f[i]=f[i+1]+a[i]-ave;
sort(f+1,f+n+1);
Xn=-f[(n+1)/2];
FOR(i,1,n)
ans+=abs(Xn+f[i]);
cout<<ans;
return 0;
}