2019年牛客多校第一场 C题Euclidean Distance 暴力+数学
题目链接
题意
给你\(n\)个数\(a_i\),要你在满足下面条件下使得\(\sum\limits_{i=1}^{n}(a_i-p_i)^2\)最小(题目给的\(m\)只是为了将\(a_i\)变成一个整数,那么我们就当此处的\(p_i\)扩大为题目给的\(m\)倍,然后把\(m\)放到分母去,以下不再解释):
- \(p_i\in\mathbb{R}\);
- \(p_i\geq 0,i\in[1,n]\);
- \(\sum\limits_{i=1}^{n}p_i=m\)。
思路
由于叉姐的题解太高深了,本菜鸡完全看不懂(爆哭),因此我们从其他角度来求解本题。
首先根据题目要求的式子和条件可以发现我们能做的只是将\(p_i\)合理赋值使得\(\sum\limits_{i=1}^{n}(a_i-p_i)^2\)最小,且\(a_i\in[-m,m],p_i\in[0,m]\),那么\(p_i\)只能将\(a_i\)的值不断减小而不能增加(即使\(a_i<0\)),因此我们就可以通过调节\(p_i\)的值使得\(a_i\)的最大值尽可能的小,且\(\sum\limits_{i=1}^{n}p_i=m\)。
假设我们进行处理前\(i-1\)后\(p\)的和还剩下\(las\),前\(i\)个的\(a\)的值都已经被削到了\(a_i\),那么:
- 如果\(i\times|(a[i+1]-a[i])|\leq las\),那么\(las=las-i\times|(a[i+1]-a[i])|\);
- 否则,就记录这个位置为\(idx\),并且\(break\)(\(idx\)的初始值为\(n\))。
其中的\(idx\)就是说我们可以通过调节\(p_i\)的值使得前\(idx\)个数都相等且等于\(a_{idx}-\frac{las}{idx}\),因此最后答案是\(\frac{idx\times(a_{idx}-\frac{las}{idx})^2+\sum\limits_{i=idx+1}^{n}a_{idx}^2}{m^2}\)(因为我们最初始时将\(a_i,p_i\)都扩大了\(m\)倍,将\(m\)丢到了分母)。
如果没看懂我们可以通过分析样例\(3\)来帮助理解:
首先我们将\(a\)数组排序得到:
\(3\) \(1\) \(-2\)
- 处理前\(1\)个数,此时\(las=10>1\times|1-3|=2\),于是我们将\(a_1\)变成\(1\),\(las\)消耗\(2\);
- 处理前\(2\)个数,此时\(las=8>2\times|-2-1|=6\),于是我们将\(a_1,a_2\)变成\(-2\),\(las\)消耗\(6\);
- 处理前\(3\)个数,此时\(las=2,a_1=a_2=a_3=-2\),由于\(las\)最后要变成\(0\)且\(a_i\)的最大值要尽可能小,那么我们需要均匀分配,所以最后\(a_1=a_2=a_3=-2-\frac{2}{3}=-\frac{8}{3}\)。
所以最后答案为\(\frac{(-\frac{8}{3})^2\times 3}{10\times 10}=\frac{16}{75}\)。
\(update\):
证明这个写法的正确性:
假设现在有两个数\(a,b(a\geq b)\),总的可以减少的数量为\(m\)。
1.首先证明当\(a-b\geq m\)时全放在\(a\)上最优:
设\(m\)中有\(x(1\leq x\leq m)\)用在\(b\)上,那么和为\((a-m+x)^2+(b-x)^2\),全用在\(a\)上的话和为\((a-m)^2+b^2\),两者做差:
&(a-m+x)^2+(b-x)^2-(a-m)^2-b^2&\\
=&(a-m)^2+2x(a-m)+x^2+b^2-2bx+x^2-(a-m)^2-b^2&\\
=&2x^2+2x(a-m)-2bx&\\
=&2x^2+2x(a-b-m)\geq 0&
\end{aligned}
\]
2.再证明当\(a=b,m\geq 0\)时均分最优:
设\(m\)中有\(x(1\leq x< \frac{m}{2})\)用在\(b\)上,那么和为\((a-m+x)^2+(b-x)^2\),将其化简:
&(a-m+x)^2+(b-x)^2&\\
=&(a-m)^2+2(a-m)x+x^2+b^2-2bx+x^2&\\
=&(a-m)^2+b^2+2x^2+2(a-m-b)x&\\
=&(a-m)^2+b^2+2(x^2-mx)(\text{题目给定的}a=b)&
\end{aligned}
\]
由于前一半和\(x\)无关,而后一半\(x^2-mx=(x-\frac{m}{2})^2-\frac{m^2}{4}\)在\(x=\frac{m}{2}\)时取最小值。
最后我们来讨论有\(n\)个数分配\(m\),其中\(a,b\)分别为\(n\)个数中的最大和次大值时为什么当\(m>a-b\)时每次将最大值减小到次大值是最优的的情况:
- \((1).\)首先如果将\(m\)全部减到一个数上,那么肯定是减小最大值是最优的:\((a-m)^2+c^2-a^2-(c-m)^2=a^2-2am+m^2+c^2-a^2-c^2+2cm-m^2=2m(c-a)<0(c\)为剩余\(n-1\)个数中的任意一个数);
- \((2).\)如果分配到两个数上那么也一定时分到最大值和次大值上,理由同上;那么此时我们应该怎么分配最优呢?我们发现当\(a\)减少到\(a=b\)之后如果再减少\(a\)的话,\(b\)就已经大于\(a\)成为新的最大值了,那么再减小\(a\)肯定不是最优解(理由为\((1)\)),因此只能将最大值\(a\)减小到次大值\(b\),然后根据上面的\(2\)得知均匀分配最优;
- 分配到任意多个数的情况基本和\((2)\)相同。
因此我们可以得知本题的解决策略是正确的。
(如果想法或者证明过程有错误,还请各位大佬指正~)
代码实现如下
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("D://Code//in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)
const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 1e5 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
int n, m;
int a[maxn];
int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif // ONLINE_JUDGE
while(~scanf("%d%d", &n, &m)) {
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
sort(a + 1, a + n + 1, [](int a, int b){return a > b;});
int idx = n;
int las = m;
for(int i = 1; i < n; ++i) {
if(i * abs(a[i+1] - a[i]) > las) {
idx = i;
break;
} else {
las -= i * abs(a[i+1] - a[i]);
}
}
LL num1 = 1LL * (idx * a[idx] - las) * (idx * a[idx] - las);
LL num2 = 1LL * idx * m * m;
for(int i = idx + 1; i <= n; ++i) {
num1 += 1LL * a[i] * a[i] * idx;
}
LL tmp = __gcd(num1, num2);
num1 /= tmp, num2 /= tmp;
if(num2 == 1) printf("%lld\n", num1);
else printf("%lld/%lld\n", num1, num2);
}
return 0;
}
2019年牛客多校第一场 C题Euclidean Distance 暴力+数学的更多相关文章
- 2019年牛客多校第一场B题Integration 数学
2019年牛客多校第一场B题 Integration 题意 给出一个公式,求值 思路 明显的化简公式题,公式是分母连乘形式,这个时候要想到拆分,那如何拆分母呢,自然是裂项,此时有很多项裂项,我们不妨从 ...
- 2019年牛客多校第一场 I题Points Division 线段树+DP
题目链接 传送门 题意 给你\(n\)个点,每个点的坐标为\((x_i,y_i)\),有两个权值\(a_i,b_i\). 现在要你将它分成\(\mathbb{A},\mathbb{B}\)两部分,使得 ...
- 2019年牛客多校第一场 H题XOR 线性基
题目链接 传送门 题意 求\(n\)个数中子集内所有数异或为\(0\)的子集大小之和. 思路 对于子集大小我们不好维护,因此我们可以转换思路变成求每个数的贡献. 首先我们将所有数的线性基的基底\(b\ ...
- 2019年牛客多校第一场 B题 Integration 数学
题目链接 传送门 思路 首先我们对\(\int_{0}^{\infty}\frac{1}{\prod\limits_{i=1}^{n}(a_i^2+x^2)}dx\)进行裂项相消: \[ \begin ...
- 2019年牛客多校第一场 E题 ABBA DP
题目链接 传送门 思路 首先我们知道\('A'\)在放了\(n\)个位置里面是没有约束的,\('B'\)在放了\(m\)个位置里面也是没有约束的,其他情况见下面情况讨论. \(dp[i][j]\)表示 ...
- Cutting Bamboos(2019年牛客多校第九场H题+二分+主席树)
题目链接 传送门 题意 有\(n\)棵竹子,然后有\(q\)次操作,每次操作给你\(l,r,x,y\),表示对\([l,r]\)区间的竹子砍\(y\)次,每次砍伐的长度和相等(自己定砍伐的高度\(le ...
- 2019年牛客多校第二场 F题Partition problem 爆搜
题目链接 传送门 题意 总共有\(2n\)个人,任意两个人之间会有一个竞争值\(w_{ij}\),现在要你将其平分成两堆,使得\(\sum\limits_{i=1,i\in\mathbb{A}}^{n ...
- MAZE(2019年牛客多校第二场E题+线段树+矩阵乘法)
题目链接 传送门 题意 在一张\(n\times m\)的矩阵里面,你每次可以往左右和下三个方向移动(不能回到上一次所在的格子),\(1\)表示这个位置是墙,\(0\)为空地. 现在有\(q\)次操作 ...
- Kth Minimum Clique(2019年牛客多校第二场D题+k小团+bitset)
目录 题目链接 题意 思路 代码 题目链接 传送门 题意 找第\(k\)小团. 思路 用\(bitset\)来标记每个结点与哪些结点直接有边,然后进行\(bfs\),在判断新加入的点与现在有的点是否都 ...
随机推荐
- [Docker] 六步运行一个 sentry 实例
# 6步, https://hub.docker.com/_/sentry/ # 依赖Redisdocker run -d --name sentry-redis redis:3.2.12 # 依赖p ...
- flutter本地环境的安装以及编辑器的配置
由于本文图片比较多,所有都缩小了不少,点击图片就可以放大看到原始图片 使用镜像 cmd打开终端,贴上以下代码,以加入到环境变量中,如果添加失败,可以手动添加 export PUB_HOSTED_URL ...
- Versioning information could not be retrieved from the NuGet package repository. Please try again later.
Versioning information could not be retrieved from the NuGet package repository. Please try again la ...
- jquery+css 点赞喜欢特效
百度盘链接 https://pan.baidu.com/s/1Nu8fiUrdffsNd6usTsUESg 密码 mps4 效果:
- 第二周、ubuntu的简单介绍与使用
一.复习第一周的大致内容:1.UNIX与Linux.ubuntu系统UNIX是1971年贝尔实验室的肯·汤普逊.丹尼斯·里奇,合作研发一款通过的操作系统,多用户.多任务.安全.稳定,收费.Linux是 ...
- Fiddler的使用总结
关于Fiddler的使用过程中的总结: 1. 配置手机抓包的过程,以后再补充 2.使用Fiddler发送请求 1) 第一步 抓取接口,获取请求方式,以及请求参数 2) 第二步 请求接口 点击Exec ...
- Kafka理解
1. 引言 最近使用Kafka做消息队列时,完成了基本的消息发送与接收,已上线运行.一方面防止出现Bug时自己不能及时定位问题,一方面网上的配置可能还可以更加优化,决定去了解下Kafka. 2. 配置 ...
- C#JsonConvert.DeserializeObject反序列化json字符
需求:需要把第一个id替换掉,在序列化成json dynamic dyn = Newtonsoft.Json.JsonConvert.DeserializeObject(json); foreach ...
- sqlserver安装教程
1 安装步骤:http://jingyan.baidu.com/article/359911f573f71657fe030603.html 2 当提示装载第二张光盘时,在DAEMON Tools中把第 ...
- Java自学-控制流程 If
Java的 If 条件语句 条件判断 示例 1 : if if(表达式1){ 表达式2: } 如果表达式1的值是true, 就执行表达式2 public class HelloWorld { publ ...