题目描述
有
n
n
n 个小朋友坐成一圈,每人有
a
i
a_i
ai 个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为
1
1
1 。
输入格式
小朋友个数
n
n
n,下面
n
n
n 行
a
i
a_i
ai 。
输出格式
求使所有人获得均等糖果的最小代价。
输入输出样例
输入 #1
4
1
2
5
4
输出 #1
4
说明/提示
对于
100
%
100\%
100% 的数据
n
≤
1
0
6
n\le 10^6
n≤106 。
思路:
设每个人原来拥有糖果数量为 A i A_i Ai ,每次向右传递数量为 X i X_i Xi (向左为 − X i -X_i −Xi ),糖果平均数为 a v g avg avg 。
则有
原
有
的
−
向
右
传
出
去
的
+
左
边
传
进
来
的
=
平
均
数
原有的-向右传出去的+左边传进来的=平均数
原有的−向右传出去的+左边传进来的=平均数
即
A
i
−
X
i
+
X
i
+
1
=
a
v
g
A_i-X_i+X_{i+1}=avg
Ai−Xi+Xi+1=avg
联立方程
{
A
1
−
X
1
+
X
2
=
a
v
g
A
2
−
X
2
+
X
3
=
a
v
g
⋯
A
n
−
1
−
X
n
−
1
+
X
n
=
a
v
g
A
n
−
X
n
+
X
1
=
a
v
g
\left\{ \begin{aligned} A_1-X_1+X_{2}&=avg \\ A_2-X_2+X_{3}&=avg \\ \cdots \\ A_{n-1}-X_{n-1}+X_{n}&=avg \\ A_n-X_n+X_{1}&=avg \\ \end{aligned} \right.
⎩⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎧A1−X1+X2A2−X2+X3⋯An−1−Xn−1+XnAn−Xn+X1=avg=avg=avg=avg
整理得
{
−
X
1
+
X
2
=
a
v
g
−
A
1
−
X
2
+
X
3
=
a
v
g
−
A
2
⋯
−
X
n
−
1
+
X
n
=
a
v
g
−
A
n
−
1
X
1
−
X
n
=
a
v
g
−
A
n
\left\{ \begin{aligned} -X_1+X_{2}&=avg-A_1 \\ -X_2+X_{3}&=avg-A_2 \\ \cdots \\ -X_{n-1}+X_{n}&=avg-A_{n-1} \\ X_{1}-X_n&=avg-A_n \\ \end{aligned} \right.
⎩⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎧−X1+X2−X2+X3⋯−Xn−1+XnX1−Xn=avg−A1=avg−A2=avg−An−1=avg−An
其增广矩阵
B
=
(
A
β
)
=
[
−
1
1
0
⋯
0
0
a
v
e
−
A
1
0
−
1
1
⋯
0
0
a
v
e
−
A
2
⋮
⋱
⋮
⋮
0
0
0
⋯
−
1
1
a
v
e
−
A
n
−
1
1
0
0
⋯
0
−
1
a
v
e
−
A
n
]
B=(A \;\;\beta)= \left[ \begin{array}{cccccc|c} -1 & 1 & 0 & \cdots & 0 & 0 & ave-A_1\\ 0 & -1 & 1 & \cdots & 0 & 0 & ave-A_2\\ \vdots & & \ddots& & & \vdots & \vdots\\ 0 & 0 & 0 & \cdots & -1 & 1 & ave-A_{n-1}\\ 1 & 0 & 0 & \cdots & 0 & -1 & ave-A_{n}\\ \end{array} \right]
B=(Aβ)=⎣⎢⎢⎢⎢⎢⎡−10⋮011−10001⋱00⋯⋯⋯⋯00−1000⋮1−1ave−A1ave−A2⋮ave−An−1ave−An⎦⎥⎥⎥⎥⎥⎤
化为行最简形
[
1
0
0
⋯
0
−
1
(
∑
i
=
1
n
−
1
A
i
)
−
(
n
−
1
)
a
v
e
0
1
0
⋯
0
−
1
(
∑
i
=
2
n
−
1
A
i
)
−
(
n
−
2
)
a
v
e
⋮
⋱
⋮
⋮
0
0
0
⋯
1
−
1
A
n
−
1
−
a
v
e
0
0
0
⋯
0
0
0
]
\left[ \begin{array}{cccccc|c} 1 & 0 & 0 & \cdots & 0 & -1 & (\sum_{i=1}^{n-1}A_i)-(n-1)ave\\ 0 & 1 & 0 & \cdots & 0 & -1 & (\sum_{i=2}^{n-1}A_i)-(n-2)ave\\ \vdots & & \ddots& & & \vdots & \vdots\\ 0 & 0 & 0 & \cdots & 1 & -1 & A_{n-1}-ave\\ 0 & 0 & 0 & \cdots & 0 & 0 & 0\\ \end{array} \right]
⎣⎢⎢⎢⎢⎢⎡10⋮00010000⋱00⋯⋯⋯⋯0010−1−1⋮−10(∑i=1n−1Ai)−(n−1)ave(∑i=2n−1Ai)−(n−2)ave⋮An−1−ave0⎦⎥⎥⎥⎥⎥⎤
得方程组的解为
{
X
1
=
X
n
+
(
∑
i
=
1
n
−
1
A
i
)
−
(
n
−
1
)
a
v
e
X
2
=
X
n
+
(
∑
i
=
2
n
−
1
A
i
)
−
(
n
−
2
)
a
v
e
⋮
X
n
−
1
=
X
n
+
A
n
−
1
−
a
v
e
X
n
=
X
n
∈
R
\left\{ \begin{aligned} X_1&=X_n+(\sum_{i=1}^{n-1}A_i)&-(n-1)ave\\ X_2&=X_n+(\sum_{i=2}^{n-1}A_i)&-(n-2)ave\\ &\qquad \qquad \qquad \vdots \\ X_{n-1}&=X_n+A_{n-1}&-ave\\ X_n&=X_n&\in{\Bbb R}\\ \end{aligned} \right.
⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧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
=
1
n
∣
X
i
∣
\sum_{i=1}^{n}|X_i|
∑i=1n∣Xi∣ 的最小值
观察方程组的解,发现所有项都有相同的变量
X
n
X_n
Xn ,所以构造函数
X
x
=
X
n
+
f
(
x
)
X_x=X_n+f(x)
Xx=Xn+f(x)
即
f
(
x
)
=
∑
i
=
x
n
−
1
A
i
−
(
n
−
x
)
a
v
e
f(x)=\sum_{i=x}^{n-1}A_i \; -(n-x)ave
f(x)=i=x∑n−1Ai−(n−x)ave
所以
∑
i
=
1
n
∣
X
i
∣
=
∣
X
n
+
f
(
1
)
∣
+
⋯
+
∣
X
n
+
f
(
n
)
∣
=
∑
i
=
1
n
∣
X
n
+
f
(
i
)
∣
\sum_{i=1}^{n}|X_i|=|X_n+f(1)|+\cdots+|X_n+f(n)|=\sum_{i=1}^{n}|X_n+f(i)|
i=1∑n∣Xi∣=∣Xn+f(1)∣+⋯+∣Xn+f(n)∣=i=1∑n∣Xn+f(i)∣
而
∑
i
=
1
n
∣
X
n
+
f
(
i
)
∣
\sum_{i=1}^{n}|X_n+f(i)|
∑i=1n∣Xn+f(i)∣ 可以看作数轴上的点
X
n
X_n
Xn 到点
−
f
(
i
)
,
i
∈
[
1
,
n
]
-f(i),i\in [1,n]
−f(i),i∈[1,n] 的距离之和
那么 X n X_n Xn 应取最中间的点(高中结论,函数图像为平底锅( n n n 为偶数)或尖底锅( n n n 为奇数))
于是我们只要找到
−
f
(
i
)
,
i
∈
[
1
,
n
]
-f(i),i\in [1,n]
−f(i),i∈[1,n] 的中位数,把他赋值给
X
n
X_n
Xn 即可
将其代入
∑
i
=
1
n
∣
X
n
+
f
(
i
)
∣
\sum_{i=1}^{n}|X_n+f(i)|
∑i=1n∣Xn+f(i)∣ 即为本题答案
P S : PS: PS: f ( x ) f(x) f(x) 有递归求法 f ( i ) = f ( i + 1 ) + A i − a v e f(i)=f(i+1)+A_i-ave f(i)=f(i+1)+Ai−ave ,从后往前循环即可,不要用 f ( x ) = ∑ i = x n − 1 A i − ( n − x ) a v e f(x)=\sum_{i=x}^{n-1}A_i \; -(n-x)ave f(x)=∑i=xn−1Ai−(n−x)ave ,后者会导致 T L E TLE TLE
A C AC AC 代码
#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;
}