糖果传递

老师准备了一堆糖果, 恰好n 个小朋友可以分到数目一样多的糖果. 老师要n 个小朋友去拿糖果, 然后围着圆桌坐好, 第1 个小朋友的左边是第n 个小朋友,其他第i 个小朋友左边是第i-1 个小朋友。大家坐好后, 老师发现, 有些小朋友抢了很多的糖果, 有的小朋友只得到了一点点糖果, 甚至一颗也没有, 设第i 个
小朋友有ai 颗糖果. 小朋友们可以选择将一些糖果给他左边的或者右边的小朋友, 通过”糖果传递”最后使得每个小朋友得到的糖果数是一样多的, 假设一颗糖果从一个小朋友传给另一个小朋友的代价是1, 问怎样传递使得所耗的总代价最小。
输入
   输入文件第一行一个正整数n,表示小朋友的个数.
   接下来n行,每行一个整数ai,表示第i 个小朋友得到的糖果的颗数.
输出
   输出只有一个数, 表示最小代价.
样例
Input

4

1
2
5
4

Output

4
数据范围
   30%的测试数据, n<=1000.
   100%的测试数据, n<=1000000.
   ai>=0, 保证ai在长整型范围内, ai的总和在int64/long long范围内.

 

解析:这道题用骗分的方法,只能得10分 到20 分。 看看数据,100W,就知道要用线性或者 nlogn的算法。

而且,nlogn的算法也不能用上很多的常数级,要不照样超时。

这道题完全是数学方法,

设第i个小朋友分给第i-1个小朋友的糖果数为Pi(注意, Pi可正可负负数理解成为第i-1个小朋友分给第i个小朋友-Pi个糖果),P1为第一个小朋友分给第n个小朋友的, 显然最后的答案就是要求|P1| + |P2| +..+ |Pn|的最小值.

而我们的最总目的是,将Pi全部用P1表示。

设ave为最终每个人拿到的糖果数目,也就是平均数。

则ave=(-Pi) + (Pi+1+ a[i],

设w[i]=ave – a[i], 则变成 w[i]=(-Pi) + (Pi+1),

设S[i]=w[1] + w[2] +…+ w[i] 则PP+ S[i-1],

|P1| + |P2| +..+ |Pn| = |P1| + |P1+S[1]| +..+ |P1+S[n-1]|

设Q=-P1

则 原式变为|0-Q| + |s[1]-Q| +..+ |s[n-1]-Q|

这个式子可以看成 求 0,s[1],s[2]…s[n-1]到 Q的 最短距离之和,

这这个数列的中位数就是Q值。


原文地址:http://blog.sina.com.cn/s/blog_75683c7f0100q4va.html

点赞