社区讨论
萌新92pts求救
P1721[NOI2016] 国王饮水记参与者 1已保存回复 1
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @lo37x7nb
- 此快照首次捕获于
- 2023/10/24 02:15 2 年前
- 此快照最后确认于
- 2023/10/24 02:15 2 年前
rt,#19 #20都卡不进精度。。快调崩了。。
做法大概是决策单调性的分治,带
CPP// This is an empty program with decimal lib
#include <cstdlib>
#include <cstring>
#include <string>
// ---------- decimal lib start ----------
const int PREC = 6000;
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 ----------
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define db long double
#define rep(i,a,b) for(int i=a;i<=b;i++)
int n,k,p;
const int N=1e4+10;
int _h[N],h[N],tot;
int s[N];
db f[N][1010];
int fr[N][1010];
void dp(int j,int l,int r,int L,int R){
if(l>r)return;
int i=(l+r+1)/2;
int pos;db ans=-1e18;
rep(k,L,min(R,i-1)){
if((f[k][j-1]+s[i]-s[k])/(i-k+1)>ans){
//printf("-- %d,%d\n",k,j-1);
ans=(f[k][j-1]+s[i]-s[k])/(i-k+1);
pos=k;
}
}
f[i][j]=ans;
fr[i][j]=pos;
dp(j,l,i-1,L,pos);
dp(j,i+1,r,pos,R);
}
Decimal calc(signed i,signed j){
if(j==0)return h[0];
signed pos=fr[i][j];
return (calc(pos,j-1)+s[i]-s[pos])/(i-pos+1);
}
signed main(){
cin>>n>>k>>p;
rep(i,1,n)cin>>_h[i];
h[tot=0]=_h[1];
rep(i,1,n)if(_h[i]>_h[1]){
h[++tot]=_h[i];
}
sort(h,h+tot+1);
s[0]=h[0];
rep(i,1,tot){
s[i]=s[i-1]+h[i];
}
rep(i,0,tot)f[i][0]=h[0];
//rep(k,0,tot+1)printf("dp[%d][%d]= %.5Lf\n",k,0,f[k][0]);
rep(j,1,min({tot,k,1000ll})){
dp(j,0,tot,0,tot);
//rep(k,0,tot+1)printf("dp[%d][%d]= %.5Lf\n",k,j,f[k][j]);
}
cout<<calc(tot,min({tot,k,1000ll})).to_string((int)p*2);
}
回复
共 1 条回复,欢迎继续交流。
正在加载回复...