糖果传递
糖果传递
有 个小朋友坐成一圈,每人有 个糖果。
每人只能给左右两人传递糖果。
每人每次传递一个糖果代价为 。
求使所有人获得均等糖果的最小代价。
输入格式
第一行输入一个正整数 ,表示小朋友的个数。
接下来 行,每行一个整数 ,表示第 个小朋友初始得到的糖果的颗数。
输出格式
输出一个整数,表示最小代价。
数据范围
,
,
数据保证一定有解。
输入样例:
4 1 2 5 4
输出样例:
4
解题思路
很难想到这是一道数学题。
设为第个人给前一个人(。其中当时,前一个人为第个人)的糖果数量。注意,这里的可以是正数或者负数。当为正数,表示第个人给前一个人糖果;当为负数,表示前一个人给第个人糖果。
因此整一个代价为,我们的目标就是求的最小值。
设为所有糖果的平均数,最后每个人手上的糖果数量应该为,列方程:
发现秩不为,方程有无穷多解。所有式子加起来会得到常数等于常数,即有个独立的方程,个未知数。所以存在一个自由元,可以用某一个来表示其他所有的。
移项,把上述方程变为
从最后一个方程开始,每次都往前加上一个方程,得到
这样我们就可以用来表示其他所有的了。
代入中,有对于上面中的每一项,我们可以发现都是减去一个常数,因此可以写成
其中,。
我们可以惊奇的发现,要求上式的最小值,等价于要找到一个,使得分别到的距离的和最小。
当取到的中位数时,上式就可以取到最小值。这个模型可以参考货仓选址这一题。这里简单证明一下。
先假定。
我们把式子的每一项分成若干组,第项和第项为一组,第项和第项为一组,以此类推,如果为奇数,那么第项就独自为一组,得到由绝对值不等式,得到意味着当,才取到等号。对于式子的其他组,同理可得。最后式子变为我们可以发现,当每一组都取到等号,上式才可以取到最小值。因为我们一开始规定了,因此可以发现要给每一组都取到等号,的取值区间都在不断缩小,要一直到最后一组都要满足。可以发现就是取的中位数(如果为奇数,中位数就是,偶数的话,取或都可以)。
当然,我们还可以从几何意义去考虑,可以发现只有当在这个区间内,到与的距离之和才会最小,其他组也是这样分析,最后得到的结论相同。
最后我们来看看是怎么求的。
看回上面的方程组,可以发现,,......,。
可以发现递推式。
AC代码如下:
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 5 const int N = 1e6 + 10; 6 7 int a[N]; 8 long long c[N]; 9 10 int main() { 11 int n; 12 scanf("%d", &n); 13 14 long long sum = 0; 15 for (int i = 1; i <= n; i++) { 16 scanf("%d", a + i); 17 sum += a[i]; 18 } 19 20 int avg = sum / n; 21 22 // 通过递推式求ci 23 for (int i = n; i; i--) { 24 c[i] = c[i + 1] - avg + a[i]; 25 } 26 27 sort(c + 1, c + n + 1); // 排序,使得ci是递增的顺序。由于ci的位置不会影响答案,因此使得ci为递增的序列,方便求中位数 28 29 long long ret = 0; 30 for (int i = 1; i <= n + 1 >> 1; i++) { 31 ret += c[n - i + 1] - c[i]; // 最小值就是每个点到中位数的距离的和,也就是每组区间的长度的和 32 } 33 printf("%lld", ret); 34 35 return 0; 36 }
参考资料
AcWing 122. 糖果传递(蓝桥杯C++ AB组辅导课):https://www.acwing.com/video/723/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/15947208.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2021-03-01 关于C++中构造函数的常见疑问