Spreading the Wealth UVA - 11300
题意:
有n个人坐成一圈,每个人有A【i】,问怎样传递可以使每个人的金币一样,求最小传递次数。
思路:
- 先设置每个人最后的金币值为M。
- 设第
i
i
i个人给
i
−
1
i-1
i−1,
x
i
x_i
xi个金币;
i
+
1
i+1
i+1给
i
i
i,
x
i
+
1
x_{i+1}
xi+1个金币。
(特别地
: i i i给 i − 1 i-1 i−1,是 x i x_i xi个金币。那么反过来 i − 1 i-1 i−1给 i i i就是 − x i -x_i −xi个金币)
A 1 − x 1 + x 2 = M A_1-x_1+x_2=M A1−x1+x2=M
A 2 − x 2 + x 3 = M A_2-x_2+x_3=M A2−x2+x3=M
A 3 − x 3 + x 4 = M A_3-x_3+x_4=M A3−x3+x4=M
…
A n − x n + x 1 = M A_n-x_n+x_1=M An−xn+x1=M - 求出每个
x
i
x_i
xi
x 2 = M − A 1 + x 1 = x 1 − c 1 x_2=M-A_1+x_1 = x_1 - c_1 x2=M−A1+x1=x1−c1
x 3 = 2 M − A 1 − A 2 + x 1 = x 1 − c 2 x_3=2M-A_1-A_2+x_1 = x_1 - c_2 x3=2M−A1−A2+x1=x1−c2
x 4 = 3 M − A 1 − A 2 − A 3 + x 1 = x 1 − c 3 x_4=3M-A_1-A_2-A_3+x_1 = x_1 - c_3 x4=3M−A1−A2−A3+x1=x1−c3 - 那么ans = ∣ x 1 ∣ + ∣ x 2 ∣ + ∣ x 3 ∣ + . . . + ∣ x n ∣ |x_1|+|x_2|+|x_3|+...+|x_n| ∣x1∣+∣x2∣+∣x3∣+...+∣xn∣
- 即 ans = ∣ x 1 ∣ + ∣ x 1 − c 1 ∣ + ∣ x 1 − c 2 ∣ + . . . + ∣ x 1 − c n − 1 ∣ |x_1|+|x_1 - c_1|+|x_1 - c_2|+...+|x_1 - c_{n-1}| ∣x1∣+∣x1−c1∣+∣x1−c2∣+...+∣x1−cn−1∣
- 把 x 1 x_1 x1设置为这么多数的中位数即可。
AC
#include <iostream>
#include <bits/stdc++.h>
#define For(i,x,y) for(int i=(x); i<=(y); i++)
#define fori(i,x,y) for(int i=(x); i<(y); i++)
#define rep(i,y,x) for(int i=(y); i>=(x); i--)
#define mst(x,a) memset(x,a,sizeof(x))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<int,int>pa;
typedef pair<ll,ll>pai;
const int maxn = 1e6+10;
ll c[maxn];
int main()
{
//ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int n;
while(~scanf("%d", &n)){
ll sum = 0, x;
For(i,1,n)scanf("%lld", &x), sum += x, c[i] = sum;
sum /= n;
c[0] = 0;
fori(i,1,n)c[i] -= sum*i;
sort(c, c+n);
ll mid = c[n/2], ans = 0;
fori(i,0,n)ans += abs(mid-c[i]);
printf("%lld\n", ans);
}
return 0;
}