题意:
圆桌旁边坐着nn个人,每个人有一定数量的金币,金币的总数能被nn整除。每个人可以给他左右相邻的人一些金币,最终使得每个人的金币数量相等。您的任务是求出被转手的金币的数量的最小值。
解题思路:
本题要点:
1、最后每个人拿到的金币就是每个人初始金币的平均值(设为
a
v
g
avg
avg)。
2、对于相邻的两个人只会其中一个给另一个若干金币(两个人都给的话会抵消),不妨设第
i
i
i个人给第
i
−
1
i-1
i−1个人若干金币。
3、如果确定了一对相邻人给的金币,那么其它的全部确定。
4、答案就是每对相邻的人给的金币的和(其实是绝对值的和)。
重点在第三条,不妨设第
1
1
1个人给了第
n
n
n个人
x
x
x个金币,那么现在第
n
n
n个人有
a
[
n
]
+
x
a[n]+x
a[n]+x个金币,他还需要
a
v
g
−
(
a
[
n
]
+
x
)
avg-(a[n]+x)
avg−(a[n]+x),也就是说需要的这些金币只能由第
n
−
1
n-1
n−1个人给他,那么其实就是第
n
n
n个人给了第
n
−
1
n-1
n−1个人
(
a
[
n
]
+
x
)
−
a
v
g
(a[n]+x)-avg
(a[n]+x)−avg金币,以此类推:
第
n
−
1
n-1
n−1个人给第
n
−
2
n-2
n−2个人
(
a
[
n
]
+
a
[
n
−
1
]
+
x
)
−
2
∗
a
v
g
(a[n]+a[n-1]+x)-2*avg
(a[n]+a[n−1]+x)−2∗avg
…
第
2
2
2个人给第
1
1
1个人
(
a
[
n
]
+
a
[
n
−
1
]
+
.
.
+
a
[
1
]
+
x
)
−
(
n
−
1
)
∗
a
v
g
(a[n]+a[n-1]+..+a[1]+x)-(n-1)*avg
(a[n]+a[n−1]+..+a[1]+x)−(n−1)∗avg
整理一下得
1、第
i
i
i个人给第
i
−
1
i-1
i−1个人
(
i
>
1
)
(i>1)
(i>1)了
x
−
(
i
−
1
)
∗
m
+
(
a
[
n
]
+
a
[
n
−
1
]
+
.
.
.
+
a
[
n
−
i
+
1
]
)
x-(i-1)*m+(a[n]+a[n-1]+...+a[n-i+1])
x−(i−1)∗m+(a[n]+a[n−1]+...+a[n−i+1])个金币。
2、第
1
1
1个人给了第
n
n
n个人
x
x
x个金币。
结果就是他们的绝对值的和,几何意义就是
x
x
x到其它点的距离,就是其它点的中位数,最后计算一下就好了。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
long long a[maxn];
int main()
{
int n;
while(cin>>n)
{
long long sum=0;
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
sum+=a[i];
}
vector<long long> v;
v.push_back(0);
long long m =sum/n;
sum=0;
for(int i=n;i>1;i--)
{
sum+=(m-a[i]);
v.push_back(sum);
}
sort(v.begin(),v.end());
long long ans=0,avg=v[n/2];
for(int i=0;i<n;i++)
ans+=abs(v[i]-avg);
cout<<ans<<endl;
}
return 0;
}