蓝书第一章 例题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 分金币的主要内容,如果未能解决你的问题,请参考以下文章