蓝书第一章 例题3 分金币

Posted 行码棋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝书第一章 例题3 分金币相关的知识,希望对你有一定的参考价值。

题目链接👈请点击

题目大意:
一个圆桌n个人,每个人都有一定数量的金币,金币总数能够被n整除。每个人必须给他左边或者右边一些金币,最后使每个人的金币数相等。求转手的金币数量的最小值。转手的金币数指的是每个人给出去的金币数量之和。

思路:
x 1 , x 2 , x 3 . . . x n x_1,x_2,x_3...x_n x1,x2,x3...xn分别为第1,2,3,…n个人给前面的人的金币数。
当值为负值时,说明前面的人送给后面的人金币。

整理了笔记,好难整理~😭😭😭

先是这样:
在这里插入图片描述

后来是这样:看下面的还行吧
在这里插入图片描述

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 1e6+5;
ll a[N],s[N],c[N];

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	int n;
	while(cin>>n)
	{
		s[0]=0;
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];
			s[i] = s[i-1]+a[i];//记录前缀和
		}
		ll m = s[n]/n;
		c[0]=0;
		for(int i=1;i<=n;i++)
			c[i] = s[i]-i*m; //求c[i]
		//c[0]到c[n-1]相当于那n个点
		sort(c,c+n); //对0到n-1个点的坐标进行排序
		ll x = c[(n-1+1)/2];//求中位数,如果是偶数个点,取中间两个点的前一个点的位置,如果是奇数,取中间的点
		ll ans = 0;
		for(int i=1;i<=n;i++)
			ans += abs(x-c[i-1]);//注意取绝对值
		cout<<ans<<'\\n';
	}
	return 0;
 } 

中位数的这种技巧还是经常出现的,下面是一道方法非常类似的一道题,用到的技巧也是非常类似,可以对比对比,练习练习

Codeforces Round #703 (Div. 2)B(求中位数)

以上是关于蓝书第一章 例题3 分金币的主要内容,如果未能解决你的问题,请参考以下文章

蓝书 第一章 例题10 正整数序列

蓝书 第一章 例题5 蚂蚁 uva

蓝书 第一章 例题2 突击战

大白书第一章

蓝书 第一章 例题14 填充正方形

小粉书第一章