zoukankan      html  css  js  c++  java
  • 分金币(Spreading the Wealth,UVa 11300)

    分金币

    题目描述

    给定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
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    POJ 1795 DNA Laboratory
    CodeForces 303B Rectangle Puzzle II
    HDU 2197 本源串
    HDU 5965 扫雷
    POJ 3099 Go Go Gorelians
    CodeForces 762D Maximum path
    CodeForces 731C Socks
    HDU 1231 最大连续子序列
    HDU 5650 so easy
    大话接口隐私与安全 转载
  • 原文地址:https://www.cnblogs.com/qingang/p/5223557.html
Copyright © 2011-2022 走看看