题目描述
输入描述
输入由几个测试用例组成,并通过文件结束而终止.
每个测试用例的第一行包含两个整数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