zoukankan      html  css  js  c++  java
  • UVa 11300 Spreading the Wealth 数学题

    题目大意:有n 个人围坐在一个圆桌旁,每个人手中有一定数量的金币,金币的总数能够被n整除,现在每个人可以给自己旁边的两个人传递金币,要使得每个人手中的金币数相同,问最少要经过多少次的传递,假设每次只能给一个金币。

    解题报告:感觉这题就是一道纯粹的数学题,代数思想很重要。我们可以假设x2是第二个人给第一个人的金币的数量,注意这里若x2是整数,表示第二个人给第一个人金币,若x2是负数,则表示第一个人给第二个人金币,同理x3表示第三个人给第二个人的金币数量,由于桌子是圆的,所以x1就表示第1个人给第n个的金币数量。假设第i个人他一开始手上有Ai个金币,他给了i-1个人xi个金币,然后i+1个人又给了他x(i+1)个金币,所以他现在手上的金币数是Ai-xi+x(i+1),又因为最后要达到所有人手上的金币数相同,所以假设最后每个人手上有M个金币,M=总的金币数/n,所以就有方程Ai-xi+x(i+1)=M,就有

    x2=x1-(A1-M)

    x3=x1-(A1+A2-2*M);

    ........

    所以最后一共要传递的次数就等于x1+x2+x3+......xn,即|x1-(A1-M)|,   |x1-(A1+A2-2*M)|....,而这个又可以看成是在一条数轴上的一个点到n-1个点的距离之和,和明显就是中位数了,所以求出中位数就可以求出所有的和了。这题要注意的是数据量会比较大,要用long long。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cmath>
     5 #include<algorithm>
     6 
     7 const int MAXS=1000000+5;
     8 
     9 long long C[ MAXS ] , X[ MAXS ] ; 
    10 int main ( ) {
    11     long long n,M;
    12     while(scanf("%lld",&n)!=EOF) {
    13         long long  d,x1,sum;
    14         C[0]=0;
    15         for(int i=1;i<=n;++i) {
    16             scanf("%lld",&d);
    17             C[i]=C[i-1]+d;
    18         }
    19         M=C[n]/n;
    20         for( int i=1;i<n;++i)
    21         C[i]-=i*M;
    22         std::sort(C+1,C+n);
    23         if(n&1)
    24         x1=(C[(n-1)/2]+C[(n-1)/2+1])/2;
    25         else x1=C[n/2];
    26         sum=abs(x1);
    27         for(int i=1;i<n;++i)
    28         sum+=abs(x1-C[i]);
    29         printf("%lld\n",sum);
    30     }
    31     return 0;
    32 }
    View Code
  • 相关阅读:
    MySQL Explain学习笔记
    postman测试文件上传接口教程
    URLDecoder异常Illegal hex characters in escape (%)
    第三章 jQuery总结 参考文本
    史上最简单的一道面试题!坑人吧
    cookie和session的关联关系
    服务器配置
    Rancher 添加主机无法显示、添加主机无效的解决办法
    .NET Core 跨平台 串口通讯 ,Windows/Linux 串口通讯,flyfire.CustomSerialPort 的使用
    .Net Core 跨平台应用使用串口、串口通信 ,可能出现的问题、更简洁的实现方法
  • 原文地址:https://www.cnblogs.com/xiaxiaosheng/p/3116024.html
Copyright © 2011-2022 走看看