NOI2016 国王饮水记
NOI2016 国王饮水记
题意:
自己看
题解:
这题是大结论题,推荐这篇博客
结论找出来后不难做,但是,他卡你有没有看说明书!!!
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fo(i,l,r) for(int i=l;i<=r;i++)
#define of(i,l,r) for(int i=l;i>=r;i--)
#define fe(i,u) for(int i=head[u];i;i=e[i].next)
using namespace std;
typedef long long ll;
inline void open(const char *s)
{
#ifndef ONLINE_JUDGE
char str[20];
sprintf(str,"in%s.txt",s);
freopen(str,"r",stdin);
// sprintf(str,"out%s.txt",s);
// freopen(str,"w",stdout);
#endif
}
inline int rd()
{
static int x,f;
x=0;f=1;
char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return f>0?x:-x;
}
// ---------- decimal lib start ----------
const int PREC = 3100;
class Decimal {
public:
Decimal();
Decimal(const std::string &s);
Decimal(const char *s);
Decimal(int x);
Decimal(long long x);
Decimal(double x);
bool is_zero() const;
// p (p > 0) is the number of digits after the decimal point
std::string to_string(int p) const;
double to_double() const;
friend Decimal operator + (const Decimal &a, const Decimal &b);
friend Decimal operator + (const Decimal &a, int x);
friend Decimal operator + (int x, const Decimal &a);
friend Decimal operator + (const Decimal &a, long long x);
friend Decimal operator + (long long x, const Decimal &a);
friend Decimal operator + (const Decimal &a, double x);
friend Decimal operator + (double x, const Decimal &a);
friend Decimal operator - (const Decimal &a, const Decimal &b);
friend Decimal operator - (const Decimal &a, int x);
friend Decimal operator - (int x, const Decimal &a);
friend Decimal operator - (const Decimal &a, long long x);
friend Decimal operator - (long long x, const Decimal &a);
friend Decimal operator - (const Decimal &a, double x);
friend Decimal operator - (double x, const Decimal &a);
friend Decimal operator * (const Decimal &a, int x);
friend Decimal operator * (int x, const Decimal &a);
friend Decimal operator / (const Decimal &a, int x);
friend bool operator < (const Decimal &a, const Decimal &b);
friend bool operator > (const Decimal &a, const Decimal &b);
friend bool operator <= (const Decimal &a, const Decimal &b);
friend bool operator >= (const Decimal &a, const Decimal &b);
friend bool operator == (const Decimal &a, const Decimal &b);
friend bool operator != (const Decimal &a, const Decimal &b);
Decimal & operator += (int x);
Decimal & operator += (long long x);
Decimal & operator += (double x);
Decimal & operator += (const Decimal &b);
Decimal & operator -= (int x);
Decimal & operator -= (long long x);
Decimal & operator -= (double x);
Decimal & operator -= (const Decimal &b);
Decimal & operator *= (int x);
Decimal & operator /= (int x);
friend Decimal operator - (const Decimal &a);
// These can't be called
friend Decimal operator * (const Decimal &a, double x);
friend Decimal operator * (double x, const Decimal &a);
friend Decimal operator / (const Decimal &a, double x);
Decimal & operator *= (double x);
Decimal & operator /= (double x);
private:
static const int len = PREC / 9 + 1;
static const int mo = 1000000000;
static void append_to_string(std::string &s, long long x);
bool is_neg;
long long integer;
int data[len];
void init_zero();
void init(const char *s);
};
Decimal::Decimal() {
this->init_zero();
}
Decimal::Decimal(const char *s) {
this->init(s);
}
Decimal::Decimal(const std::string &s) {
this->init(s.c_str());
}
Decimal::Decimal(int x) {
this->init_zero();
if (x < 0) {
is_neg = true;
x = -x;
}
integer = x;
}
Decimal::Decimal(long long x) {
this->init_zero();
if (x < 0) {
is_neg = true;
x = -x;
}
integer = x;
}
Decimal::Decimal(double x) {
this->init_zero();
if (x < 0) {
is_neg = true;
x = -x;
}
integer = (long long)x;
x -= integer;
for (int i = 0; i < len; i++) {
x *= mo;
if (x < 0) x = 0;
data[i] = (int)x;
x -= data[i];
}
}
void Decimal::init_zero() {
is_neg = false;
integer = 0;
memset(data, 0, len * sizeof(int));
}
bool Decimal::is_zero() const {
if (integer) return false;
for (int i = 0; i < len; i++) {
if (data[i]) return false;
}
return true;
}
void Decimal::init(const char *s) {
this->init_zero();
is_neg = false;
integer = 0;
// find the first digit or the negative sign
while (*s != 0) {
if (*s == '-') {
is_neg = true;
++s;
break;
} else if (*s >= 48 && *s <= 57) {
break;
}
++s;
}
// read the integer part
while (*s >= 48 && *s <= 57) {
integer = integer * 10 + *s - 48;
++s;
}
// read the decimal part
if (*s == '.') {
int pos = 0;
int x = mo / 10;
++s;
while (pos < len && *s >= 48 && *s <= 57) {
data[pos] += (*s - 48) * x;
++s;
x /= 10;
if (x == 0) {
++pos;
x = mo / 10;
}
}
}
}
void Decimal::append_to_string(std::string &s, long long x) {
if (x == 0) {
s.append(1, 48);
return;
}
char _[30];
int cnt = 0;
while (x) {
_[cnt++] = x % 10;
x /= 10;
}
while (cnt--) {
s.append(1, _[cnt] + 48);
}
}
std::string Decimal::to_string(int p) const {
std::string ret;
if (is_neg && !this->is_zero()) {
ret = "-";
}
append_to_string(ret, this->integer);
ret.append(1, '.');
for (int i = 0; i < len; i++) {
// append data[i] as "%09d"
int x = mo / 10;
int tmp = data[i];
while (x) {
ret.append(1, 48 + tmp / x);
tmp %= x;
x /= 10;
if (--p == 0) {
break;
}
}
if (p == 0) break;
}
if (p > 0) {
ret.append(p, '0');
}
return ret;
}
double Decimal::to_double() const {
double ret = integer;
double k = 1.0;
for (int i = 0; i < len; i++) {
k /= mo;
ret += k * data[i];
}
if (is_neg) {
ret = -ret;
}
return ret;
}
bool operator < (const Decimal &a, const Decimal &b) {
if (a.is_neg != b.is_neg) {
return a.is_neg && (!a.is_zero() || !b.is_zero());
} else if (!a.is_neg) {
// a, b >= 0
if (a.integer != b.integer) {
return a.integer < b.integer;
}
for (int i = 0; i < Decimal::len; i++) {
if (a.data[i] != b.data[i]) {
return a.data[i] < b.data[i];
}
}
return false;
} else {
// a, b <= 0
if (a.integer != b.integer) {
return a.integer > b.integer;
}
for (int i = 0; i < Decimal::len; i++) {
if (a.data[i] != b.data[i]) {
return a.data[i] > b.data[i];
}
}
return false;
}
}
bool operator > (const Decimal &a, const Decimal &b) {
if (a.is_neg != b.is_neg) {
return !a.is_neg && (!a.is_zero() || !b.is_zero());
} else if (!a.is_neg) {
// a, b >= 0
if (a.integer != b.integer) {
return a.integer > b.integer;
}
for (int i = 0; i < Decimal::len; i++) {
if (a.data[i] != b.data[i]) {
return a.data[i] > b.data[i];
}
}
return false;
} else {
// a, b <= 0
if (a.integer != b.integer) {
return a.integer < b.integer;
}
for (int i = 0; i < Decimal::len; i++) {
if (a.data[i] != b.data[i]) {
return a.data[i] < b.data[i];
}
}
return false;
}
}
bool operator <= (const Decimal &a, const Decimal &b) {
if (a.is_neg != b.is_neg) {
return a.is_neg || (a.is_zero() && b.is_zero());
} else if (!a.is_neg) {
// a, b >= 0
if (a.integer != b.integer) {
return a.integer < b.integer;
}
for (int i = 0; i < Decimal::len; i++) {
if (a.data[i] != b.data[i]) {
return a.data[i] < b.data[i];
}
}
return true;
} else {
// a, b <= 0
if (a.integer != b.integer) {
return a.integer > b.integer;
}
for (int i = 0; i < Decimal::len; i++) {
if (a.data[i] != b.data[i]) {
return a.data[i] > b.data[i];
}
}
return true;
}
}
bool operator >= (const Decimal &a, const Decimal &b) {
if (a.is_neg != b.is_neg) {
return !a.is_neg || (a.is_zero() && b.is_zero());
} else if (!a.is_neg) {
// a, b >= 0
if (a.integer != b.integer) {
return a.integer > b.integer;
}
for (int i = 0; i < Decimal::len; i++) {
if (a.data[i] != b.data[i]) {
return a.data[i] > b.data[i];
}
}
return true;
} else {
// a, b <= 0
if (a.integer != b.integer) {
return a.integer < b.integer;
}
for (int i = 0; i < Decimal::len; i++) {
if (a.data[i] != b.data[i]) {
return a.data[i] < b.data[i];
}
}
return true;
}
}
bool operator == (const Decimal &a, const Decimal &b) {
if (a.is_zero() && b.is_zero()) return true;
if (a.is_neg != b.is_neg) return false;
if (a.integer != b.integer) return false;
for (int i = 0; i < Decimal::len; i++) {
if (a.data[i] != b.data[i]) return false;
}
return true;
}
bool operator != (const Decimal &a, const Decimal &b) {
return !(a == b);
}
Decimal & Decimal::operator += (long long x) {
if (!is_neg) {
if (integer + x >= 0) {
integer += x;
} else {
bool last = false;
for (int i = len - 1; i >= 0; i--) {
if (last || data[i]) {
data[i] = mo - data[i] - last;
last = true;
} else {
last = false;
}
}
integer = -x - integer - last;
is_neg = true;
}
} else {
if (integer - x >= 0) {
integer -= x;
} else {
bool last = false;
for (int i = len - 1; i >= 0; i--) {
if (last || data[i]) {
data[i] = mo - data[i] - last;
last = true;
} else {
last = false;
}
}
integer = x - integer - last;
is_neg = false;
}
}
return *this;
}
Decimal & Decimal::operator += (int x) {
return *this += (long long)x;
}
Decimal & Decimal::operator -= (int x) {
return *this += (long long)-x;
}
Decimal & Decimal::operator -= (long long x) {
return *this += -x;
}
Decimal & Decimal::operator /= (int x) {
if (x < 0) {
is_neg ^= 1;
x = -x;
}
int last = integer % x;
integer /= x;
for (int i = 0; i < len; i++) {
long long tmp = 1LL * last * mo + data[i];
data[i] = tmp / x;
last = tmp - 1LL * data[i] * x;
}
if (is_neg && integer == 0) {
int i;
for (i = 0; i < len; i++) {
if (data[i] != 0) {
break;
}
}
if (i == len) {
is_neg = false;
}
}
return *this;
}
Decimal & Decimal::operator *= (int x) {
if (x < 0) {
is_neg ^= 1;
x = -x;
} else if (x == 0) {
init_zero();
return *this;
}
int last = 0;
for (int i = len - 1; i >= 0; i--) {
long long tmp = 1LL * data[i] * x + last;
last = tmp / mo;
data[i] = tmp - 1LL * last * mo;
}
integer = integer * x + last;
return *this;
}
Decimal operator - (const Decimal &a) {
Decimal ret = a;
// -0 = 0
if (!ret.is_neg && ret.integer == 0) {
int i;
for (i = 0; i < Decimal::len; i++) {
if (ret.data[i] != 0) break;
}
if (i < Decimal::len) {
ret.is_neg = true;
}
} else {
ret.is_neg ^= 1;
}
return ret;
}
Decimal operator + (const Decimal &a, int x) {
Decimal ret = a;
return ret += x;
}
Decimal operator + (int x, const Decimal &a) {
Decimal ret = a;
return ret += x;
}
Decimal operator + (const Decimal &a, long long x) {
Decimal ret = a;
return ret += x;
}
Decimal operator + (long long x, const Decimal &a) {
Decimal ret = a;
return ret += x;
}
Decimal operator - (const Decimal &a, int x) {
Decimal ret = a;
return ret -= x;
}
Decimal operator - (int x, const Decimal &a) {
return -(a - x);
}
Decimal operator - (const Decimal &a, long long x) {
Decimal ret = a;
return ret -= x;
}
Decimal operator - (long long x, const Decimal &a) {
return -(a - x);
}
Decimal operator * (const Decimal &a, int x) {
Decimal ret = a;
return ret *= x;
}
Decimal operator * (int x, const Decimal &a) {
Decimal ret = a;
return ret *= x;
}
Decimal operator / (const Decimal &a, int x) {
Decimal ret = a;
return ret /= x;
}
Decimal operator + (const Decimal &a, const Decimal &b) {
if (a.is_neg == b.is_neg) {
Decimal ret = a;
bool last = false;
for (int i = Decimal::len - 1; i >= 0; i--) {
ret.data[i] += b.data[i] + last;
if (ret.data[i] >= Decimal::mo) {
ret.data[i] -= Decimal::mo;
last = true;
} else {
last = false;
}
}
ret.integer += b.integer + last;
return ret;
} else if (!a.is_neg) {
// a - |b|
return a - -b;
} else {
// b - |a|
return b - -a;
}
}
Decimal operator - (const Decimal &a, const Decimal &b) {
if (!a.is_neg && !b.is_neg) {
if (a >= b) {
Decimal ret = a;
bool last = false;
for (int i = Decimal::len - 1; i >= 0; i--) {
ret.data[i] -= b.data[i] + last;
if (ret.data[i] < 0) {
ret.data[i] += Decimal::mo;
last = true;
} else {
last = false;
}
}
ret.integer -= b.integer + last;
return ret;
} else {
Decimal ret = b;
bool last = false;
for (int i = Decimal::len - 1; i >= 0; i--) {
ret.data[i] -= a.data[i] + last;
if (ret.data[i] < 0) {
ret.data[i] += Decimal::mo;
last = true;
} else {
last = false;
}
}
ret.integer -= a.integer + last;
ret.is_neg = true;
return ret;
}
} else if (a.is_neg && b.is_neg) {
// a - b = (-b) - (-a)
return -b - -a;
} else if (a.is_neg) {
// -|a| - b
return -(-a + b);
} else {
// a - -|b|
return a + -b;
}
}
Decimal operator + (const Decimal &a, double x) {
return a + Decimal(x);
}
Decimal operator + (double x, const Decimal &a) {
return Decimal(x) + a;
}
Decimal operator - (const Decimal &a, double x) {
return a - Decimal(x);
}
Decimal operator - (double x, const Decimal &a) {
return Decimal(x) - a;
}
Decimal & Decimal::operator += (double x) {
*this = *this + Decimal(x);
return *this;
}
Decimal & Decimal::operator -= (double x) {
*this = *this - Decimal(x);
return *this;
}
Decimal & Decimal::operator += (const Decimal &b) {
*this = *this + b;
return *this;
}
Decimal & Decimal::operator -= (const Decimal &b) {
*this = *this - b;
return *this;
}
// ---------- decimal lib end ----------
const int N=8010;
Decimal ans;
int n,K,p,h[N],q[N],ql,qr,fr[N][20],s[N];
double f[N][20];
struct node{
double x,y;
}hh,b[N];
inline double calc(node a,node b){return (b.y-a.y)/(b.x-a.x);}
inline Decimal gao(int i,int j)
{
if(!j)return Decimal(h[1]);
return (gao(fr[i][j],j-1)+Decimal(s[i])-Decimal(s[fr[i][j]]))/(i-fr[i][j]+1);
}
int main()
{
n=rd();K=rd();p=rd();h[1]=rd();
fo(i,2,n){h[i]=rd();if(h[i]<h[1])i--,n--;}
sort(h+1,h+n+1);fo(i,1,n)s[i]=s[i-1]+h[i];
K=min(K,n);fo(i,1,n)f[i][0]=h[1];
int lim=min(K,14);
fo(j,1,lim){
q[ql=qr=1]=1;b[1].x=0;b[1].y=s[1]-f[1][j-1];
fo(i,2,n){
hh.x=i;hh.y=s[i];
while(ql<qr&&calc(b[q[ql]],hh)<calc(b[q[ql+1]],hh))ql++;
b[i].x=i-1;b[i].y=s[i]-f[i][j-1];fr[i][j]=q[ql];
f[i][j]=s[i]-s[q[ql]]+f[q[ql]][j-1];f[i][j]/=(double)(i-q[ql]+1);
while(ql<qr&&calc(b[q[qr-1]],b[q[qr]])>calc(b[q[qr]],b[i]))qr--;
q[++qr]=i;
}
}
int m=n-K+lim;
double mx=0;int pos;
fo(j,0,lim)if(f[m][j]>mx)mx=f[m][j],pos=j;
ans=gao(m,pos);
fo(i,m+1,n)ans=(ans+h[i])/2;
cout<<ans.to_string(p+3);
return 0;
}