• UVA11300分金币


    题意:
          圆桌旁作者n个人,每个人都有一定数量的金币,他们每次可以给相邻的人一枚金币(可以给多次),问所有人金币数都相同的话最少要给多少次金币。


    思路: 
          这个题目感觉很好,首先我们可以假设每个人都向他前面的人给出了xi的金币,x1表示1这个人给了n这个人(因为是环)多少金币,x2表示2给了以多少金币,xi可以使负数,负数说明是反着给的x2=-4说明是一给了二4枚金币,这样我们就可以列出来一些方程组了
    ,假设M是平均数,Ai表示第i个人的金币数,那么有


    A1-x1+x2=M  ->               x2=x1-(A1-M)= x1-C1   设C1=A1-M
    A2-x2+x3=M  ->x3 = x2-(A2-M)=x1-C1-(A2-M)= x1-C2   设C2=(A1-M)+(A2-M)
    同理                                   x3= x1-C3   设C3= (A1-M)+(A2-M)+(A3-M)
    我们用含有A1的式子推出x2,用含有A2的退出x3...所以我们没有必要用最后一个式子,还有一点就是 x1 = x1 - C0 那么C0=0;
    这样推到之后就变成我们是要求 |x1| + |x1-C1| + |x2-C2|......
    那么把他们和一维坐标联系起来,是不是就是求所有点到x1点(Ci构成的点)的距离和的最小值了,这样我们只要求出x1就行了,其实这个x1就是所有C的中位数,为什么是这样这个很好理解,我们可以在纸上画一画,比如当前的x1左边有4个点,右边有5个点,那么把x1向右移动一小块距离d(不要跨过右边的点)我们会发现整体是左边增加4d,右边减少5d所以我们要往左移,不能往右移,最后奇数的情况就是中间的那个数最优(中位数),偶数的时候是中间的那两个之间的位置(包括中间的那两个)的区间都是最优的,还可以用中位数表示。



    #include<stdio.h>
    #include<algorithm>


    #define N 1000000 + 10


    using namespace std;


    long long num[N];
    long long C[N];


    long long abss(long long x)
    {
       return x > 0 ? x : -x;



    int main ()
    {
       int n ,i;
       long long Ans ,Sum ,M;
       while(~scanf("%d" ,&n))
       {
          for(Sum = 0 ,i = 1 ;i <= n ;i ++)
          {
             scanf("%lld" ,&num[i]);
             Sum += num[i];
          }
          M = Sum / n;
          C[0] = 0;
          for(i = 1 ;i < n ;i ++)
          C[i] = C[i-1] + num[i] - M;
          sort(C ,C + n);
          long long x1 = C[n/2];
          for(Ans = 0 ,i = 0 ;i < n ;i ++)
          Ans += abss(x1 - C[i]);
          printf("%lld " ,Ans);
       }
       return 0;
    }
          
          
          
          
          
          
          
       
     





  • 相关阅读:
    如何从ORACLE数据库生成HBM和JAVA
    timer
    工作流研究
    linux date命令设置时间
    耶基斯多得森曲线
    朋友考我的一个基础语法题
    微软企业库(一)
    标记属性
    Word自动化撤销、重做功能
    汇编中的ASSUME
  • 原文地址:https://www.cnblogs.com/csnd/p/12062679.html
Copyright © 2020-2023  润新知