题面
题意
给出一排球,初始全为白色,每次随机选择一段区间染黑,全黑时停止操作,问操作的期望次数。
做法
首先设pi表示i次完成的期望,这样答案就是1*p1+2*p2+3*p3…………
也就等于(p1+p2+p3………)+(p2+p3………)+(p3………)…….
令qi表示i次未全部染黑的期望次数,那么qi=p(i+1)+p(i+2)…………………..
因此答案就可以转化为q0+q1+q2+q3+q4+q5………………
可以考虑2^n(暂时这样想)枚举最后一步染黑的点,然后就可以知道之前可以染cnt段区间而不染黑最后一步要染黑的点,并算出其概率o,利用容斥算出每种情况对答案的贡献,就是cnt/(1/(1-o))*(-1)^(k+1).
然后发现答案仅与区间个数cnt,概率o以及白点数量的奇偶性有关,就可以dp:
dp[i][j][k]表示第i个点是白点时,此时有j种区间,且白点个数的奇偶性为k,最后统计对答案的贡献即可。
因为精度要求比较高,所以需要高精度。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
// ---------- decimal lib start ----------
const int PREC = 30;
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);
static const int len = PREC / 9 + 1;
static const int mo = 1000000000;
static void append_to_string(std::string &s, long long x);
private:
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 ----------
#define ll long long
#define db double
#define D Decimal
ll n=50,dp[60][3010][2],T;
D ans[60];
inline ll calc(ll u)
{
return u*(u+1)/2;
}
int main()
{
ll i,j,k,a;
int b;
D tmp;
dp[0][0][0]=1;
for(i=0; i<=n; i++)
{
for(j=0; j<=calc(n); j++)
{
if(dp[i][j][0])
{
for(k=i+1; k<=n; k++)
{
dp[k][j+calc(k-i-1)][1]+=dp[i][j][0];
}
}
if(dp[i][j][1])
{
for(k=i+1; k<=n; k++)
{
dp[k][j+calc(k-i-1)][0]+=dp[i][j][1];
}
}
}
}
for(i=1; i<=n; i++)
{
for(j=0; j<=i; j++)
{
for(k=0; k<=calc(n); k++)
{
if(dp[j][k][0])
{
tmp=a=dp[j][k][0]*calc(i);
b=calc(i)-k-calc(i-j);
if(b) ans[i]-=tmp/b;
}
if(dp[j][k][1])
{
tmp=a=dp[j][k][1]*calc(i);
b=calc(i)-k-calc(i-j);
if(b) ans[i]+=tmp/b;
}
}
}
}
for(i=1; i<=n; i++) ans[i]+=5e-16;
cin>>T;
while(T--)
{
scanf("%d",&n);
cout<<ans[n].to_string(15)<<endl;
}
}