1045: [HAOI2008] 糖果传递

题目:传送门(双倍经验3293

题解:

   一开始想着DP贪心一顿乱搞,结果就GG了

十分感谢hzwer大佬写的毒瘤数论题解:

  首先,最终每个小朋友的糖果数量可以计算出来,等于糖果总数除以n,用ave表示。
  假设标号为i的小朋友开始有Ai颗糖果,Xi表示第i个小朋友给了第i-1个小朋友Xi颗糖果,如果Xi<0,说明第i-1个小朋友给了第i个小朋友Xi颗糖果,X1表示第一个小朋友给第n个小朋友的糖果数量。 所以最后的答案就是ans=|X1| + |X2| + |X3| + ……+ |Xn|。
  对于第一个小朋友,他给了第n个小朋友X1颗糖果,还剩A1-X1颗糖果;但因为第2个小朋友给了他X2颗糖果,所以最后还剩A1-X1+X2颗糖果。根据题意,最后的糖果数量等于ave,即得到了一个方程:A1-X1+X2=ave。
  同理,对于第2个小朋友,有A2-X2+X3=ave。最终,我们可以得到n个方程,一共有n个变量,但是因为从前n-1个方程可以推导出最后一个方程,所以实际上只有n-1个方程是有用的。
  尽管无法直接解出答案,但可以用X1表示出其他的Xi,那么本题就变成了单变量的极值问题。
  对于第1个小朋友,A1-X1+X2=ave  ->  X2=ave-A1+X1 = X1-C1(假设C1=A1-ave,下面类似)
  对于第2个小朋友,A2-X2+X3=ave  ->  X3=ave-A2+X2=2ave-A1-A2+X1=X1-C2
  对于第3个小朋友,A3-X3+X4=ave  ->  X4=ave-A3+X3=3ave-A1-A2-A3+X1=X1-C3……
  对于第n个小朋友,An-Xn+X1=ave。
    我们希望Xi的绝对值之和尽量小,即|X1| + |X1-C1| + |X1-C2| + ……+ |X1-Cn-1|要尽量小。注意到|X1-Ci|的几何意义是数轴上的点X1到Ci的距离,所以问题变成了:给定数轴上的n个点,找出一个到他们的距离之和尽量小的点,而这个点就是这些数中的中位数。
  
  这里给出一点小小的证明:

  数轴上任意找一个点,它左边有4个点,右边有2个点,把该点往左移动一点点,不要移动太多,以免碰到其他输入点。假设移动了d单位距离,则该点到左边4个点的距离各减少d,该点都右边2个点的距离各增加d,但总的来说,距离之和减少了2d。

  同理,该点的左边有2个点,右边有4个点时,类似,不过此时应该是向右移动。

  换句话说,只要该点的左右两边的输入点个数不一样多,就不是最优解。那什么情况下,左右点一样多勒?如果输入点有奇数个,则最优解应该是中间那个点即中位数。如果有偶数个,则可以位于最中间两个点的任意位置(还是中位数)。

代码:

 #include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
int n;LL a[],c[],sum;
int main()
{
scanf("%d",&n);sum=;
for(int i=;i<=n;i++)scanf("%lld",&a[i]),sum+=a[i];sum/=n;
memset(c,,sizeof(c));for(int i=;i<=n;i++)c[i]=c[i-]+a[i]-sum;
sort(c+,c+n+);LL mid;
if(n&)mid=c[(n+)/];else mid=c[n/];
LL ans=;for(int i=;i<=n;i++)ans+=abs(c[i]-mid);
printf("%lld\n",ans);
return ;
}

bzoj1045: [HAOI2008] 糖果传递(数论)的更多相关文章

  1. 【bzoj1465/bzoj1045】糖果传递 数论

    题目描述 老师准备了一堆糖果, 恰好n个小朋友可以分到数目一样多的糖果. 老师要n个小朋友去拿糖果, 然后围着圆桌坐好, 第1个小朋友的左边是第n个小朋友, 其他第i个小朋友左边是第i-1个小朋友. ...

  2. bzoj3293 [Cqoi2011]分金币&&bzoj1045 [HAOI2008]糖果传递

    Description 圆桌上坐着n个人,每人有一定数量的金币,金币总数能被n整除.每个人可以给他左右相邻的人一些金币,最终使得每个人的金币数目相等.你的任务是求出被转手的金币数量的最小值. Inpu ...

  3. BZOJ1045 [HAOI2008] 糖果传递

    Description 有n个小朋友坐成一圈,每人有ai个糖果.每人只能给左右两人传递糖果.每人每次传递一个糖果代价为1. Input 第一行一个正整数n<=987654321,表示小朋友的个数 ...

  4. [BZOJ1045] [HAOI2008] 糖果传递 (贪心)

    Description 有n个小朋友坐成一圈,每人有ai个糖果.每人只能给左右两人传递糖果.每人每次传递一个糖果代价为1. Input 第一行一个正整数n<=,表示小朋友的个数.接下来n行,每行 ...

  5. [BZOJ1045][HAOI2008]糖果传递 (环形均分纸牌)

    题意 有n个小朋友坐成一圈,每人有ai个糖果.每人只能给左右两人传递糖果.每人每次传递一个糖果代价为1. 思路 把|s[i]-s[k]|求和即可,s[i]是A的前缀和 s[k]为s数组的中位数时,总值 ...

  6. BZOJ1045 HAOI2008糖果传递(贪心)

    显然最后每个小朋友所拥有的糖果数就是糖果数总和的平均数.设该平均数为t. 环的问题一般断成链,但这个题似乎没有什么很好的办法在枚举断点的时候快速算出答案(我甚至不知道会不会有断点) 于是我们假装把他断 ...

  7. BZOJ1045 [HAOI2008]糖果传递 && BZOJ3293 [Cqoi2011]分金币

    Description 有n个小朋友坐成一圈,每人有ai个糖果.每人只能给左右两人传递糖果.每人每次传递一个糖果代价为1. Input 第一行一个正整数nn<=1'000'000,表示小朋友的个 ...

  8. 【贪心】bzoj1045: [HAOI2008] 糖果传递

    很妙的贪心思考过程 Description 有n个小朋友坐成一圈,每人有ai个糖果.每人只能给左右两人传递糖果.每人每次传递一个糖果代价为1. Input 第一行一个正整数nn<=1'000'0 ...

  9. bzoj1045: [HAOI2008] 糖果传递(思维题)

    首先每个人一定分到的糖果都是所有糖果的平均数ave. 设第i个人给i-1个人Xi个糖果,则有Ai-Xi+X(i+1)=ave. 则A1-X1+X2=ave,A2-X2+X3=ave,A3-X3+X4= ...

随机推荐

  1. tp中使用事务

    是什么 事务是为了防止,多个操作,其中有失败,数据有部分被执行成功的时候使用的. 比如,银行,用户转账.张三钱扣了,结果李四钱还增加! 这个时候需要使用事务,确保张三钱扣了,李四的钱也增加,才真正的成 ...

  2. Swift EventKit的初学者指南–请求权限

    EventKit为获取和操作用户日历事件和提醒提供了一系列的类.在下面的教程中,我的目标是带领你走出利用EventKit建立一个应用程序的第.我的目标是带领你迈出利用EventKit建立一个应用程序的 ...

  3. EOJ 3018 查找单词

    有一个单词 W,输出它在字符串 S 中从左到右第一次出现的位置 IDX(设 S 中的第 1 个字符的位置为 1).W 只由英文字母组成,S 除英文字母和汉字之外在任何位置(包括头和尾)另有一个或多个连 ...

  4. C#6.0新增功能

    C# 6.0 版本包含许多可提高开发人员工作效率的功能. 此版本中的功能包括: 只读自动属性: 可以创建只能在构造函数中设置的只读自动属性. 自动属性初始值设定项: 可以编写初始化表达式来设置自动属性 ...

  5. js前台编码,asp.net后台解码 防止前台传值到后台为乱码

    js编码:     encodeURI() 后台解码:HttpUtility.UrlDecode()

  6. SQL Server数据库性能优化

      开篇:    最近遇到了很多性能问题,一直没来的及总结,今天正好周末抽时间总结下: 对于稍微大点的公司或者说用户多一些的公司,说白了就是数据量较大的公司,在查询数据时往往会遇到很多瓶颈.这时就需要 ...

  7. 《鸟哥的Linux私房菜》笔记——03. 磁盘分区

    Everything is a file. 常见硬件对应于 Linux 下的文件(/dev目录下) 装置 装置在Linux内的档名 SCSI/SATA/U盘硬盘机 /dev/sd[a-p] U盘 /d ...

  8. Haskell手撸Softmax回归实现MNIST手写识别

    Haskell手撸Softmax回归实现MNIST手写识别 前言 初学Haskell,看的书是Learn You a Haskell for Great Good, 才刚看到Making Our Ow ...

  9. Python中int,bool,str,格式化,少量is,已经for循环练习

    1.整数 ​ 十进制转化为二进制 ​ xxx.bit_length(). #求十进制数转化成二进制时所占用的位数 2.布尔值 ​ bool # 布尔值 - - 用于条件使用 ​ True 真 ​ Fa ...

  10. Django Views Decorator

    Django的试图函数的装饰器主要有: HTTP请求方法 条件视图处理 GZip压缩 改变页眉 缓存 官网文档 HTTP请求方法 该装饰器是设置允许访问HTTP协议的方法,装饰器在django.vie ...