这个题吧,还是有点难的,那个就是个递推
题意:
n个人围成一圈,每个人都有一些硬币,,每个人只能给左右相邻的人硬币,问最少交换几个硬币,使每个人硬币一样多;
思路:
首先要求出平均数M,每个人的硬币为numi;那么对于1,他能给予4号x1个硬币,并从2号出得到x2个硬币,那么对于1可得numi - x1 + x2 = M;
同理可得numn-xn+x1 = M
就能得到:
x2 =x1-C1 (C1 = num1 - M)
x3 = M - num2 + x2 = 2M-A1-A2+x1 = x1-x2
…
最后所求为
|x1| + |x1-C1|+…+|x1-Cn-1|,要求这个最小,那么就是要x1为这些数的中位数;
求出x1,在计算和就行了;
这个吧,是别人写的,我一开始没看懂。
后来重点来了就是把那个c2 = c1 + m - a1 .以前认为,c1,c2没联系,其实,c2 = c1 + 什么什么。。。。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MaxN = 1e6 + 5;
typedef long long LL;
LL a[MaxN] , c[MaxN];
int main()
{
int n;
while(~scanf("%d",&n)){
LL sum = 0 , num = 0;
for(int i = 1 ; i <= n ; i++)
scanf("%lld",&a[i]) , sum += a[i];
int m = (sum / n);
c[0] = 0;
// printf("m = %d\n",m);
for(int i = 1; i < n ; i++){
c[i] = c[i - 1] + a[i] - m;
}
sort(c , c + n);
// for(int i = 1 ; i < n ; i++)
// printf("c[%d] = %d\n",i , c[i]);
int flag = c[n / 2];
// printf("flag = %d\n",flag);
for(int i = 0 ; i < n ; i++){
num += abs(flag - c[i]);
}
printf("%lld\n",num);
}
}