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
  • 相关阅读:
    构建之法阅读笔记01
    最长英语单词链
    第十五周学习总结
    寻找“水王”
    Happy Necklace HDU
    Bi-shoe and Phi-shoe LightOJ
    The Embarrassed Cryptographer POJ
    Big Number HDU
    矩阵乘法模板C/C++
    Baby Step,Giant Step算法模板
  • 原文地址:https://www.cnblogs.com/qingang/p/5223557.html
Copyright © 2011-2022 走看看