UVA11300:Spreading the Wealth

来源:互联网 发布:网络上紫菀镇有原版吗 编辑:程序博客网 时间:2024/06/05 00:52

数学与算法之美在于抽象。
这题的题意是 共产主义大好!n个人坐成一圈要平分财产。
分的规则是只能和相邻两人交换。
那不妨规定一个人要给上个人钱,即 1给n x1块钱 2给1 x2块钱,3给2 x3块钱…… (xi可以为负数)
令m为平均的钱数,a[i]为初始钱数;
具体过程见代码开头的备注;

//推导/******************************************a1-x1+x2=m;->x2=x1-(al-m);a2-x2+x3=m;->x3=x1-(a1-m+a2-m);a3-x3+x4=m;->x4=x1-(a1-m+a2-m+a3-m);...........an-xn+x1=m;->x1=x1-(a1-m+a2-m+...+an-m);令c1=a1-m;  c2=c1+a2-m;  ...........  cn=c(n-1)+an-m;sum=|x1|+|x2|+|x3|+......+|xn|;   =|x1-c1|+|x1-c2|+|x1-c3|+......+|x1-cn|;(取中位数最小)x1是任意的,可取中位数;*******************************************/#include<cstdio>#include<algorithm>#include<cmath>using namespace std;typedef long long ll;ll a[1000005], c[1000005];int main() {    int n;    while (~scanf("%d", &n)) {        ll m = 0;        for (int i = 1;i <= n;i++) {            scanf("%d", &a[i]);            m += a[i];        }        m /= n;        c[1] = a[1] - m;        for (int i = 2;i <= n;i++) {            c[i] = c[i - 1] + a[i] - m;        }        sort(c+1,c+n+1);        ll x1 = c[n / 2], ans = 0;         for (int i = 1;i <= n;i++) {            ans += abs(x1 - c[i]);        }        printf("%lld\n", ans);    }    return 0;}