UVA - 11300 Spreading the Wealth

【题目描述】

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

【输入格式】

输入包含多组数据。每组数据第一行为一个整数n(n<=1000000)0),以下n行每行为一个整数,按逆时针顺序给出每个人拥有的金币数。输入结束标志为文件结束符(EOF)

【输出格式】

对于每组数据,输出被转手的金币的数量的最小值。输入保证这个值在 64位无符号整数的范围之内。

【Sample】

Input

3
100
100
100
4
1
2
5
4

Output

0
4

【Solution】

这是一道数学题

根据题意

每个人都可以给两边人传递硬币

为了简化问题

我们定向每个人i只能给下一个人x[i]枚硬币

那么我们的答案就是求\(|x_1| + |x_2| + ... + |x_n|\)的最小值

假设最终每个人分到num枚硬币

那么当前第i个人的情况是

a[i] - x[i] + x[i + 1] = num;

接下来就是推导式子

\(x_{i+1} = num - a_i + x_i\)

\(x_2 = num - a_1 + x_1\)

\(x_3 = num - a_2 + x_2\)

联立上述两个式子得到

\(x_2 = x_1 - (a_1 - num)\);

\(x_3 = x_2 - (a_1 + a_2 - 2 * num)\)

同理我们可以写出\(1\) ~ \(n\)所有的项数

所有的式子相加可以得到

$x_i = x_1 - $ \(\sum_{i = 1}^{n - 1} a_j - (n - 1) * m\)

由此可见,我们要求得答案只与\(x_1\)有关

拿一个\(tmp_i\)表示后面的一大坨\(\sum_{i = 1}^{n - 1} a_j - (n - 1) * m\)

我们的答案的表达式为

\(|x_1| + |x_2| + ... + |x_n| = |x_1| + |x_1 - tmp_2| + |x_1- tmp_3| + ... + |x_1- tmp_n|\)

根据这是一道数学题

不难想到

上述等式右边表示\(x _ 1\)到\(tmp_1\)~\(tmp_n\)的距离之和

显然,当\(x_1\)为集合$ {tmp_n} $的中位数时

该式子取得最小值

代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define int long long
using namespace std; inline int read(){
int x = 0, w = 1;
char ch = getchar();
for(; ch > '9' || ch < '0'; ch = getchar()) if(ch == '-') w = -1;
for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
return x * w;
} const int maxn = 1000010;
int a[maxn], tmp[maxn];
int num, n; signed main(){
while(scanf("%lld", &n) != EOF){
memset(a, 0, sizeof a);
memset(tmp, 0, sizeof tmp);
int ans = 0;
int sum = 0;
for(int i = 1; i <= n ;i++){
a[i] = read();
sum += a[i];
}
num = sum / n;
tmp[1] = 0;
for(int i = 1; i < n; i++){
tmp[i + 1] = num - a[i] + tmp[i];
}
sort(tmp + 1, tmp + 1 + n);
int x = tmp[n / 2];
for(int i = 1; i <= n; i++){
ans += abs(x - tmp[i]);
}
cout << ans << endl;
}
return 0;
}

UVA - 11300 Spreading the Wealth(数学题)的更多相关文章

  1. UVa 11300 Spreading the Wealth(有钱同使)

    p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: "Times New ...

  2. uva 11300 - Spreading the Wealth(数论)

    题目链接:uva 11300 - Spreading the Wealth 题目大意:有n个人坐在圆桌旁,每个人有一定的金币,金币的总数可以被n整除,现在每个人可以给左右的人一些金币,使得每个人手上的 ...

  3. UVA.11300 Spreading the Wealth (思维题 中位数模型)

    UVA.11300 Spreading the Wealth (思维题) 题意分析 现给出n个人,每个人手中有a[i]个数的金币,每个人能给其左右相邻的人金币,现在要求你安排传递金币的方案,使得每个人 ...

  4. 数学/思维 UVA 11300 Spreading the Wealth

    题目传送门 /* 假设x1为1号给n号的金币数(逆时针),下面类似 a[1] - x1 + x2 = m(平均数) 得x2 = x1 + m - a[1] = x1 - c1; //规定c1 = a[ ...

  5. Uva 11300 Spreading the Wealth(递推,中位数)

    Spreading the Wealth Problem A Communist regime is trying to redistribute wealth in a village. They ...

  6. Math - Uva 11300 Spreading the Wealth

    Spreading the Wealth Problem's Link ---------------------------------------------------------------- ...

  7. UVA 11300 Spreading the Wealth (数学推导 中位数)

    Spreading the Wealth Problem A Communist regime is trying to redistribute wealth in a village. They ...

  8. [ACM_几何] UVA 11300 Spreading the Wealth [分金币 左右给 最终相等 方程组 中位数]

    Problem A Communist regime is trying to redistribute wealth in a village. They have have decided to ...

  9. UVa 11300 Spreading the Wealth 分金币

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

随机推荐

  1. K8S-PV和PVC的实践

    一.什么是PV和PVC? PV的全称是Persistent Volume,翻译过来为持久化存储卷,是对底层的共享存储的一种抽象,PV由管理员进行创建和配置,主要含存储能力.访问模式.存储类型.回收策略 ...

  2. CORS跨域漏洞学习

    简介 网站如果存CORS跨域漏洞就会有用户敏感数据被窃取的风险. 跨域资源共享(CORS)是一种浏览器机制,可实现对位于给定域外部的资源的受控访问.它扩展了同源策略(SOP)并增加了灵活性.但是,如果 ...

  3. Cypress系列(16)- 查找页面元素的基本方法

    如果想从头学起Cypress,可以看下面的系列文章哦 https://www.cnblogs.com/poloyy/category/1768839.html 前端页面代码 后面写的 Cypress ...

  4. 20184302 2019-2020-2 《Python程序设计》实验四报告

    20184302 2019-2020-2 <Python程序设计>实验四报告 课程:<Python程序设计> 班级: 1843 姓名: 李新锐 学号:184302 实验教师:王 ...

  5. netty集群(一)-服务注册发现

    上篇文章介绍了如何搭建一个单机版本的netty聊天室:https://www.jianshu.com/p/f786c70eeccc. 一.需要解决什么问题: 当连接数超过单机的极限时,需要将netty ...

  6. @codeforces - 549E@ Sasha Circle

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定两个点集 M 与 S,求是否存在一个圆能够分割两个点集. 原 ...

  7. Communication【floyd判环+并查集】

    Communication 题目链接(点击) 题目描述 The Ministry of Communication has an extremely wonderful message system, ...

  8. 并发系列(一)——线程池源码(ThreadPoolExecutor类)简析

    前言 本文主要是结合源码去线程池执行任务的过程,基于JDK 11,整个过程基本与JDK 8相同. 个人水平有限,文中若有表达有误的,欢迎大伙留言指出,谢谢了! 一.线程池简介 1.1 使用线程池的优点 ...

  9. 获取ul下面最后一个li或ul中有多少个li

    获取ul下面最后一个li或ul中有多少个li 先获取ul的对象,再通过这个对象获取li的list用for循环取值text之类的 def set_city(self, base_info): quali ...

  10. filter()函数过滤序列

    ''' Python内建的filter()函数用于过滤序列. 和map()类似,filter()也接收一个函数和一个序列.和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据 ...