首页 > 其他 > 详细

分金币(Spreading the Wealth,UVa 11300)

时间:2016-02-27 21:55:56      阅读:181      评论:0      收藏:0      [点我收藏+]

分金币

 

题目描述

给定N个人成环状坐,每个人初始分配Ai的金币,金币总数可以被N整除,每个人可以给左右相邻的人一定数量的金币使得最终每个人的金币数量相同,求转移数量最小的方案所转移的总金币数量。

N<=1000000

有多组数据,对每组数据保证输出在long long范围之内。

样例输入

3
100
100
100
4
1
2
5
4

样例输出

0
4

分析(少打分析,今洒家也图个新鲜)

 先设Xi表示第i+1个人给第i个人(第1个人给第n个人)的金币数;ave表示分完后每个人所拥有的金币数;

 可以建立方程(最初信息储存在Ai中):

 A1-X1+X2=ave;

 A2-X2+X3=ave;

 A3-X3+X4=ave;

 。。。

An-1-Xn-1+Xn=ave;(An-Xn+X1=ave没用,前n-1个人分完后,最后一个肯定是ave个)

转一下:

X2=ave-A2+X1;                 引入变量Ci=Ai-ave:   X2=X1-C2;

。。。                                                                        。。。

Xn=ave-An-1-Xn-1;                                                  Xn=Xn-1-Cn-1=Xn-2-Cn-2-Cn-1=...

要使X2...Xn-1最小,X1就是Ci的中位数,这样就简单了,递推一下就行了;

 %I64d没改,在UVa上提交要用%lld

技术分享
#include<cstdio>
#include<algorithm>
using namespace std;
int n;
long long a[1000005],c[1000005],ave,ans;
int main()
{
    while(scanf("%d",&n)==1){
        ave=0;
        for(int i=1;i<=n;i++){scanf("%I64d",&a[i]);ave+=a[i];}
        ave/=n;
        c[0]=0;
        for(int i=1;i<n;i++) c[i]=c[i-1]+a[i]-ave;
        sort(c,c+n);
        ans=0;long long x1=c[n/2];
        for(int i=0;i<n;i++) ans+=abs(x1-c[i]);
        printf("%I64d\n",ans);
    }
    return 0;
}
View Code

 

分金币(Spreading the Wealth,UVa 11300)

原文:http://www.cnblogs.com/qingang/p/5223557.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!