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

来源

题目描述

在这里插入图片描述

输入描述

输入由几个测试用例组成,并通过文件结束而终止.
每个测试用例的第一行包含两个整数n和m,第二行包含n个整数,a 1 _1 1, a 2 _2 2…a n _n n.

输出描述

对于每个测试用例,打印一个表示结果的分数。
1 ≤ \leq n ≤ \leq 10 4 ^4 4
1 ≤ \leq m ≤ \leq 10 3 ^3 3
-m ≤ \leq a i _i i ≤ \leq m
n的和不超过5 × \times × 10^5

输入样例

1 1
0
2 3
1 2
3 10
1 -2 3

输出样例

1
0
16/75

solution

A(a 1 _1 1/m,a 2 _2 2/m…a n _n n/m)
P(p 1 _1 1,p 2 _2 2…p n _n n)
使A,P的欧拉距离最小
为方便计算,先把A,P的坐标都扩大m倍,这样求得的结果最终除以m 2 ^2 2即为最终结果
Q=P ⋅ \cdot m,q i _i i=p i _i i ⋅ \cdot m
A(a 1 _1 1,a 2 _2 2…a n _n n)
Q(q 1 _1 1,q 2 _2 2…q n _n n)
q 1 _1 1+q 2 _2 2+…+q n _n n=m
先给A从大到小排序
将m分配给每个a,使所有的a尽可能接近,可以证明这样得到的欧拉距离是最小的
详细证明请参考这篇博客

AC代码

#include<iostream>
#include<stack>
#include<vector> 
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
/*********************************************************************/
class Rational{
public:
    Rational(ll num,ll denomi);
    //运算符重载 
    friend Rational operator+(Rational x,Rational y);
    friend Rational operator-(Rational x,Rational y);
    friend Rational operator*(Rational x,Rational y);        
    friend Rational operator/(Rational x,Rational y);
    //兼容和整数的运算 
    friend Rational operator+(Rational x,ll y);
    friend Rational operator+(ll x,Rational y);
    friend Rational operator-(Rational x,ll y);        
    friend Rational operator-(ll x,Rational y);    
    friend Rational operator*(Rational x,ll y);
    friend Rational operator*(ll x,Rational y);
    friend Rational operator/(Rational x,ll y);        
    friend Rational operator/(ll x,Rational y);
    //重载比较运算符 
    friend bool operator>(Rational x,Rational y);
    friend bool operator<(Rational x,Rational y);
    friend bool operator>=(Rational x,Rational y);
    friend bool operator<=(Rational x,Rational y);
    friend bool operator==(Rational x,Rational y);
    //重载输出运算符 
 	friend ostream & operator<<(ostream &out, Rational &obj);
 	//gcd函数 
 	ll gcd(ll a, ll b){return b ? gcd(b, a % b) : a;}
	//归一化处理,比如将2/16变成1/8
	void normalize();
public:
    ll numerator;//分子
    ll denominator;//分母
}; 
Rational::Rational(ll num=1,ll denomi=1){
    numerator=num;
    denominator=denomi;
    normalize();
} 
void Rational::normalize(){
   	if(denominator<0){//保证分母大于0 
       numerator=-numerator;
       denominator=-denominator;
   	}
	ll a = abs(numerator);
	ll b = abs(denominator);
	//求两个数的最大公约数
	ll gc = gcd(a,b);
	//分子,分母分别除以最大公约数,得到最简式
	numerator/=gc;
	denominator/=gc;
}
//运算符重载 
//a    c     a*d+b*c
//—  + — = ————
//b    d       b*d
Rational operator+(Rational x,Rational y){
 ll a=x.numerator;
 ll b=x.denominator;
 ll c=y.numerator;
 ll d=y.denominator;
 ll e=a*d+c*b;
 ll f=b*d;
 return Rational(e,f);
} 
Rational operator-(Rational x,Rational y){
    y.numerator = -y.numerator;//减相当于加负数
    return x + y;
}
//a    c    a*c
//— * — = ——
//b    d    b*d
Rational operator*(Rational x,Rational y){
    ll a=x.numerator;
    ll b=x.denominator;
    ll c=y.numerator;
    ll d=y.denominator; 
    ll e=a*c;
    ll f=b*d; 
    return Rational(e,f);
}
//a    c    a*d
//— / — = ——
//b    d    b*c
Rational operator/(Rational x,Rational y){
    ll a=x.numerator;
    ll b=x.denominator;
    ll c=y.numerator;
    ll d=y.denominator; 
    ll e=a*d;
    ll f=b*c;
    return Rational(e,f);
}
//兼容和整数的运算 
Rational operator+(Rational x,ll y){
	return x + Rational(y,1); 
}
Rational operator+(ll x,Rational y){
	return Rational(x,1) + y;
}
Rational operator-(Rational x,ll y){
	return x - Rational(y,1);
}      
Rational operator-(ll x,Rational y){
	return Rational(x,1) + y;
}
Rational operator*(Rational x,ll y){
	return x*Rational(y,1); 
}
Rational operator*(ll x,Rational y){
	return Rational(x,1) * y;
}
Rational operator/(Rational x,ll y){
	return x / Rational(y,1);
}      
Rational operator/(ll x,Rational y){
	return Rational(x,1) / y;
}
//比较运算符重载    
bool operator>(Rational x,Rational y){
	Rational cha = x - y;
	return cha.numerator > 0;
} 
bool operator<(Rational x,Rational y){
	Rational cha = x - y;
	return cha.numerator < 0;
} 
bool operator>=(Rational x,Rational y){
	Rational cha = x - y;
	return cha.numerator >= 0;
} 
bool operator<=(Rational x,Rational y){
	Rational cha = x - y;
	return cha.numerator <= 0;
} 
bool operator==(Rational x,Rational y){
	Rational cha = x - y;
	return cha.numerator == 0;
} 
//输出运算符重载 
ostream & operator<<(ostream &out, Rational &obj){
	if(obj.numerator == 0)
		cout<<obj.numerator;
    else if(obj.denominator == 1)
        cout<<obj.numerator;
    else
        cout<<obj.numerator<<'/'<<obj.denominator;
    return out;
}
/***********************************************************/
const int N = (int)(1e4+5); 
int n,m;
Rational a[N];
ll x;
/***********************************************************/ 
bool cmp(Rational a,Rational b){
	if(Rational(a - b).numerator > 0)
		return true;
    else return false;
}
void solve(){
	sort(a,a+n,greater<Rational>());
	Rational cha;
	Rational mr(m,1);
	int i = 0;
	for(i=0;i<n-1;i++){
		cha = a[i]-a[i+1];
		if(mr >= cha*(i+1)){//够减 
			mr = mr - cha*(i+1);		
		}else{//不够减 		
			break;//0~i都已经减到相同,都为a[i] 
		}
	}//剩下的m平均分配给前flag+1个 
	int flag = i;
	Rational na = a[flag] - mr/(flag+1);
	Rational sum = na*na*(flag+1);
	for(int i=flag+1;i<n;i++){
		sum = sum + a[i]*a[i]; 
	}
	sum = sum/(m*m);
	cout<<sum<<endl;
}
int main(){
	ios::sync_with_stdio(false);
while(cin>>n>>m){
	for(int i=0;i<n;i++){
		cin>>x;
		a[i]=Rational(x,1);
	}		
	solve();
}		
	return 0;
}

总结

涉及内容:
模拟
分数的四则运算
gcd

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值