2019牛客暑期多校训练营(第一场)----C-Euclidean Distance

首先发出题目链接:
链接:https://ac.nowcoder.com/acm/contest/881/C
来源:牛客网
涉及:数学,gcd

点击这里回到2019牛客暑期多校训练营解题—目录贴


题目如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如题所示,题目想要得到那个最短距离的值,而不是P点的坐标,注意答案如果是整数就输出整数,否则输出分数


设距离为X,则
X m i n = ( a 1 − p 1 ) m i n 2 + ( a 2 − p 2 ) m i n 2 + . . . + ( a n − p n ) m i n 2 X_{min}=(a_1-p_1)^2_{min}+(a_2-p_2)^2_{min}+...+(a_n-p_n)^2_{min} Xmin=(a1p1)min2+(a2p2)min2+...+(anpn)min2
故需要求得 ( a 1 − p 1 ) , ( a 2 − p 2 ) , . . . , ( a n − p n ) (a_1-p_1),(a_2-p_2),...,(a_n-p_n) (a1p1),(a2p2),...,(anpn)这一些列数的最小值

且:
 
 1. p 1 + p 2 + . . . + p n = m p_1+p_2+...+p_n=m p1+p2+...+pn=m(注意,因为我没有把所有的 a i a_i ai除以m,所以所有的p值加起来等于m,最后答案再除以m就ok)
 
 2.由于 p 1 , p 2 , . . . , p n ≥ 0 p_1,p_2,...,p_n \ge0 p1,p2,...,pn0 ( a 1 − p 1 ) ≤ a 1 , ( a 2 − p 2 ) ≤ a 2 , . . . , ( a n − p n ) ≤ a n (a_1-p_1)\le a_1,(a_2-p_2)\le a_2,...,(a_n-p_n)\le a_n (a1p1)a1,(a2p2)a2,...,(anpn)an


也就是说,题目可以变成,把m的值分配给每一个 p i p_i pi,让每一个 ∣ a i − p i ∣ \left\vert a_i-p_i\right\vert aipi尽可能的小,先对所有 a i a_i ai有大到小排序,如图所示(n=5):
在这里插入图片描述
在分配的时候,我们想让每一个 a i a_i ai都尽量的小,所以我们先将m分配给比较大的 a i a_i ai(即排序后的 a 1 a_1 a1

让比较大的 a i a_i ai减小一个数b,其收益比让比较小的 a i a_i ai减去一个数b的收益大,可以证明:
假设 a 1 a_1 a1 a 2 a_2 a2大,由于收益(最小距离)是平方和状态,则明显 a 1 2 − ( a 1 − b ) 2 > a 2 2 − ( a 2 − b ) 2 a_1^2-(a_1-b)^2>a_2^2-(a_2-b)^2 a12(a1b)2>a22(a2b)2


所以首先我们将m的值分配一些给 a 1 a_1 a1来减小 a 1 a_1 a1减小到和 a 2 a_2 a2一样大,于是
在这里插入图片描述
假设此时发现m分配一些值之后,m仍然没有等于0,此时还需要继续分配,但是,此时要将剩下的m的值同时分配给 a 1 , a 2 a_1,a_2 a1a2,让它们同时减小。

也可以证明同时减小比其中一个减小的收益高

于是
在这里插入图片描述
到了此时,仍然有剩余的值,那就让 a 1 , a 2 , a 3 a_1,a_2,a_3 a1,a2,a3同时减小,但是发现,三个值减小到0的时候,m还有剩余的值,此时就需要将 a 1 , a 2 , a 3 a_1,a_2,a_3 a1,a2,a3减小到负数了,那么 ∣ a 1 ∣ ∣ a 2 ∣ ∣ a 3 ∣ \left\vert a_1\right\vert \left\vert a_2\right\vert \left\vert a_3\right\vert a1a2a3的值会增大(此时的减小就成为了亏损),但是由于m的值必须全部分配完毕,所以必须得减小。

也可以证明 a 1 , a 2 , . . , a n a_1,a_2,..,a_n a1,a2,..,an都小于0时,让它们同时减小的亏损比让某一个减少的亏损小。

假设此时m剩余的值,已经不足让 a 1 , a 2 , a 3 a_1,a_2,a_3 a1,a2,a3减小到 a 4 a_4 a4那么大,于是,在减小到某一值就会停止减小
在这里插入图片描述
此时,m=0,得到最短距离,距离为
a 1 2 + a 2 2 + . . + a 5 2 m 2 \frac {a_1^2+a_2^2+..+a_5^2}{m^2} m2a12+a22+..+a52
按照这种思路,不管n为多少,只要将m分配给所有最大的 a i a_i ai,让他们同时减小,直到m=0,那么距离就为 a 1 2 + a 2 2 + . . + a n 2 m 2 \frac {a_1^2+a_2^2+..+a_n^2}{m^2} m2a12+a22+..+an2

sort(a+1,a+n+1,greater<int>());//由大到小排序
for(i=1;i<n;i++){
	int x=a[i]-a[i+1];//每一个a[i]与a[i+1]之间的差值
	if(tot+x*i<=m)	tot+=x*i;//tot是m已经分配的值,tot+x*i用来判断m还能不能分配值,使a[1],..,a[i]到a[i+1]的位置
	else	break;//不能刚好分配
}
int rem=m-tot; //m剩余的值
//fz/fm等于前面a[1],...,a[i]最小能减少到多少
ll fz=i*a[i]-rem;
ll fm=m*i;
ll gcd=getgcd(fz*fz*i,fm*fm);
fz=fz*fz*i/gcd;fm=fm*fm/gcd;//(fz*fz*i)/(fm*fm)是前面a[1],...,a[i]对距离的贡献
for(i=i+1;i<=n;i++)	get(fm,fz,m,a[i]);//加上后面没有分配到值的a[i+1],..,a[n]对距离的贡献(a[i]*a[i])/m*m
void get(ll &fm,ll &fz,ll m,ll z){//分数加法函数
	ll gcd=getgcd(fz*m*m+z*z*fm,fm*m*m);
	fz=(fz*m*m+z*z*fm)/gcd;
	fm=fm*m*m/gcd;
	return;
}

当然,排序后分配m, a 1 , a 2 , . . . , a n − 1 a_1,a_2,...,a_{n-1} a1,a2,...,an1都减小到了 a n a_n an,发现此时m还有剩余的值,那就将 a 1 , a 2 , . . . , a n a_1,a_2,...,a_n a1,a2,...,an一起减小
在这里插入图片描述
此时刚好 a 1 = a 2 = . . . = a n , i = n a_1=a_2=...=a_n,i=n a1=a2=...=ani=n

fz=n*a[n]-rem;
fm=m*n;
ll gcd=getgcd(fz*fz*n,fm*fm);
fz=fz*fz*n/gcd;fm=fm*fm/gcd;	

举个例子
n=3,m=10,a={1,-2,3}
在这里插入图片描述

1.首先将 a 1 a_1 a1减至 a 2 a_2 a2,此时m剩余8,如图
在这里插入图片描述

2.再将 a 1 , a 2 a_1,a_2 a1,a2减到 a 3 a_3 a3,此时m剩余2
在这里插入图片描述

3.m还有剩余, a 1 , a 2 , a 3 a_1,a_2,a_3 a1,a2,a3继续减小
在这里插入图片描述

于是最短距离为
( − 8 3 ) 2 ⋅ 3 1 0 2 = 16 75 \frac {(-\frac 8{3})^2·3}{10^2}=\frac {16}{75} 102(38)23=7516


代码如下:

#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
const int maxn=1e4+5;
int n,m,a[maxn];//题目所给变量
ll getgcd(ll a,ll b){return (b==0?a:getgcd(b,a%b));}
void get(ll &fm,ll &fz,ll m,ll z){//分数加法函数
	ll gcd=getgcd(fz*m*m+z*z*fm,fm*m*m);
	fz=(fz*m*m+z*z*fm)/gcd;
	fm=fm*m*m/gcd;
	return;
}
int main(){
	while(~scanf("%d%d",&n,&m)){
		int i,tot=0;
		for(i=1;i<=n;i++)	scanf("%d",&a[i]);
		sort(a+1,a+n+1,greater<int>());//由大到小排序
		for(i=1;i<n;i++){
			int x=a[i]-a[i+1];//每一个a[i]与a[i+1]之间的差值
			if(tot+x*i<=m)	tot+=x*i;//tot是m已经分配的值,tot+x*i用来判断m还能不能分配值,使a[1],..,a[i]到a[i+1]的位置
			else	break;//不能刚好分配
		}
		int rem=m-tot;//m剩余的值
		//fz/fm等于前面a[1],...,a[i]最小能减少到多少
		ll fz=i*a[i]-rem;
		ll fm=m*i;
		ll gcd=getgcd(fz*fz*i,fm*fm);
		fz=fz*fz*i/gcd;fm=fm*fm/gcd;//约分
		//(fz*fz*i)/(fm*fm)是前面a[1],...,a[i]对距离的贡献
		for(i=i+1;i<=n;i++)	get(fm,fz,m,a[i]);//加上后面没有分配到值的a[i+1],..,a[n]对距离的贡献(a[i]*a[i])/m*m
		//下面是输出限制
		if(fm==1)	printf("%lld\n",fz);
		else	printf("%lld/%lld\n",fz,fm);
	}
	return 0;
} 
数据治理是确保数据准确性、可靠性、安全性、可用性和完整性的体系和框架。它定义了组织内部如何使用、存储、保护和共享数据的规则和流程。数据治理的重要性随着数字化转型的加速而日益凸显,它能够提高决策效率、增强业务竞争力、降低风险,并促进业务创新。有效的数据治理体系可以确保数据在采集、存储、处理、共享和保护等环节的合规性和有效性。 数据质量管理是数据治理中的关键环节,它涉及数据质量评估、数据清洗、标准化和监控。高质量的数据能够提升业务决策的准确性,优化业务流程,并挖掘潜在的商业价值。随着大数据和人工智能技术的发展,数据质量管理在确保数据准确性和可靠性方面的作用愈发重要。企业需要建立完善的数据质量管理和校验机制,并通过数据清洗和标准化提高数据质量。 数据安全与隐私保护是数据治理中的另一个重要领域。随着数据量的快速增长和互联网技术的迅速发展,数据安全与隐私保护面临前所未有的挑战。企业需要加强数据安全与隐私保护的法律法规和技术手段,采用数据加密、脱敏和备份恢复等技术手段,以及加强培训和教育,提高安全意识和技能水平。 数据流程管理与监控是确保数据质量、提高数据利用率、保护数据安全的重要环节。有效的数据流程管理可以确保数据流程的合规性和高效性,而实时监控则有助于及时发现并解决潜在问题。企业需要设计合理的数据流程架构,制定详细的数据管理流程规范,并运用数据审计和可视化技术手段进行监控。 数据资产管理是将数据视为组织的重要资产,通过有效的管理和利用,为组织带来经济价值。数据资产管理涵盖数据的整个生命周期,包括数据的创建、存储、处理、共享、使用和保护。它面临的挑战包括数据量的快速增长、数据类型的多样化和数据更新的迅速性。组织需要建立完善的数据管理体系,提高数据处理和分析能力,以应对这些挑战。同时,数据资产的分类与评估、共享与使用规范也是数据资产管理的重要组成部分,需要制定合理的标准和规范,确保数据共享的安全性和隐私保护,以及建立合理的利益分配和权益保障机制。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值