Spreading the Wealth
A Communist regime is trying to redistribute wealth in a village. They have have decided to sit everyone around a circular table. First, everyone has converted all of their properties to coins of equal value, such that the total number of coins is divisible by the number of people in the village. Finally, each person gives a number of coins to the person on his right and a number coins to the person on his left, such that in the end, everyone has the same number of coins. Given the number of coins of each person, compute the minimum number of coins that must be transferred using this method so that everyone has the same number of coins.
Input
There is a number of inputs. Each input begins with n(n<1000001), the number of people in the village. nlines follow, giving the number of coins of each person in the village, in counterclockwise order around the table. The total number of coins will fit inside an unsigned 64 bit integer.
Output
For each input, output the minimum number of coins that must be transferred on a single line.
Sample Input
3
100
100
100
4
1
2
5
4
Sample Output
0
4
美丽的Doris小妹妹告诉我,当点的数量是偶数的时候中位数是可以取两只之间的任何数的,包括两点又不仅仅局限于两点。
先证:当点数为偶数时中位数可以取中间两点中的任意一点
假设有x1,x2,x3,x4四点(已经排好序),我们取中位数为(x2+x3)/2那么中位数向左移动到x2时移动了d距离,那么左边两点减少2d,右边两点增加2d,结果仍然不增不减,所以当点数为偶数时中位数可以取中间两点中的任意一点。
再证:当点数为偶数时中位数可以取中间两点间的任意一点
由于代数分析的过程与数学模型建立的过程没有直接联系,所以可以完全的站在数学模型的角度上观察此问题,所以不影响结果。
此题应用了一个经典模型——中位数累加距离模型。通过递推的方法求解,涵盖了代数分析手法,值得学习。有兴趣的可以自行Google。
(注意:Unix/Linux环境下请使用lld ;Win环境下请使用I64d。)
附代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define MAXN 1000000+5
ll A[MAXN],C[MAXN];
int main()
{
int n;
while(scanf("%d",&n)!=EOF){
ll tot=0;
memset(A,0,sizeof(A));
memset(C,0,sizeof(C));
for(int i=0;i<n;i++){
scanf("%lld",&A[i]);
tot+=A[i];
}
ll M=tot/n;
for(int i=1;i<n;i++) C[i]=C[i-1]+A[i]-M;
sort(C,C+n);
ll x=C[n/2];
ll ans=0;
for(int i=0;i<n;i++) ans+=abs(x-C[i]);
printf("%lld\n",ans);
}
return 0;
}