Problem Description
I spin it again and again,and throw it away finally.
So now I have a row of n ball,named from 1 to n,each ball is white initially.
At each step I randomly chose a interval [l, r] and paint all ball in this interval to black.
It means every interval have a equal chance of being chosen.
And I’ll stop if all ball are black.What is the expected steps before I stop?
Input
The first line contains integer T(1<=T<=50). Denoting the number of the test cases.
Then T lines follows, each line contains an integer n (1<=n<=50).
Output
For each test cases,print the answer in a line.
Print the answer rounded to 15 decimal places.
Sample Input
3
1
2
3
Sample Output
1.000000000000000
2.000000000000000
2.900000000000000
Hint
不建议使用long double
Author
WJMZBMR
Source
2013 Multi-University Training Contest 3
Recommend
zhuyuanchen520 | We have carefully selected several similar problems for you: 6460 6459 6458 6457 6456
题目大意:
N
N
N个球排成一排,初始为白色,每次随意一个区间
[
l
,
r
]
[l,r]
[l,r]染黑,问期望染多少次能把所有球染黑
N
<
=
50
N<=50
N<=50
用
m
i
n
−
m
a
x
min-max
min−max容斥
显然可以得到式子
a
n
s
=
∑
T
⊆
S
(
−
1
)
∣
T
∣
−
1
∗
E
(
T
)
ans=\sum_{T\subseteq S}(-1)^{|T|-1}*E(T)
ans=T⊆S∑(−1)∣T∣−1∗E(T)
E
(
T
)
E(T)
E(T)表示期望染多少次能染到集合
T
T
T中的元素
现在问题就是怎么求 E ( T ) E(T) E(T),并快速统计答案
易得 E ( T ) = 总 区 间 数 合 法 区 间 数 = 总 区 间 数 总 区 间 数 − 不 合 法 区 间 数 E(T)=\frac{总区间数}{合法区间数}=\frac{总区间数}{总区间数-不合法区间数} E(T)=合法区间数总区间数=总区间数−不合法区间数总区间数
假设集合
T
T
T中的球为红球,其他为绿球,我们把每一段的绿球的个数构成一个序列
a
i
(
i
∈
[
1
,
k
]
)
{a_i}(i\in[1,k])
ai(i∈[1,k])
则不合法区间数
=
∑
i
=
1
k
a
i
∗
(
a
i
+
1
)
2
=\sum_{i=1}^k \frac{a_i*(a_i+1)}{2}
=∑i=1k2ai∗(ai+1)
故
a
n
s
=
∑
T
⊆
S
(
−
1
)
∣
T
∣
−
1
∗
n
∗
(
n
+
1
)
2
n
∗
(
n
+
1
)
2
−
∑
i
=
1
k
a
i
∗
(
a
i
+
1
)
2
ans=\sum_{T\subseteq S}(-1)^{|T|-1}*\frac{\frac{n*(n+1)}{2}}{\frac{n*(n+1)}{2}-\sum_{i=1}^k\frac{a_i*(a_i+1)}{2}}
ans=T⊆S∑(−1)∣T∣−1∗2n∗(n+1)−∑i=1k2ai∗(ai+1)2n∗(n+1)
f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k]表示前 i i i个球,第 i i i个球为红球,红球个数的奇偶性为 j ( 0 / 1 ) j(0/1) j(0/1),不合区间数为 k k k的方案数
转移的时候枚举下一段绿球即可
这题直接小数输出精度不够,得用高精度
可以把所有正的和负的先加起来(能好写很多)
#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = j;i <= k;++i)
#define repp(i,j,k) for(int i = j;i >= k;--i)
#define rept(i,x) for(int i = linkk[x];i;i = e[i].n)
#define P pair<int,int>
#define Pil pair<int,ll>
#define Pli pair<ll,int>
#define Pll pair<ll,ll>
#define pb push_back
#define pc putchar
#define mp make_pair
#define file(k) memset(k,0,sizeof(k))
#define ll long long
int rd()
{
int sum = 0;char c = getchar();bool flag = true;
while(c < '0' || c > '9') {if(c == '-') flag = false;c = getchar();}
while(c >= '0' && c <= '9') sum = sum * 10 + c - 48,c = getchar();
if(flag) return sum;
else return -sum;
}
const int N = 51;
ll f[52][2][2501];
struct point{ll zs;int xs[110];}ans,tmp;
void change(point &a,ll x,int y)
{
x -= x/y*y;
rep(i,1,100) x *= 10,a.xs[i] += x/y,x -= x/y*y;
repp(i,100,1) a.xs[i-1] += a.xs[i]/10,a.xs[i] %= 10;
a.zs += a.xs[0];a.xs[0] = 0;
}
void del()
{
ans.zs -= tmp.zs;
repp(i,100,1) ans.xs[i] -= tmp.xs[i],
ans.xs[i-1] -= ans.xs[i] < 0 ? 1 : 0,
ans.xs[i] = (ans.xs[i] + 10) % 10;
ans.zs += ans.xs[0];ans.xs[0] = 0;
}
int main()
{
f[0][0][0] = 1;
rep(i,0,N-1) rep(j,0,2500) rep(fl,0,1)
if(f[i][fl][j]) rep(k,i+1,N) f[k][fl^1][j+(k-i-1)*(k-i)/2] += f[i][fl][j];
int T = rd(),n,x;
while(T--)
{
ans.zs = 0;rep(i,0,100) ans.xs[i] = 0;
tmp.zs = 0;rep(i,0,100) tmp.xs[i] = 0;
n = rd();x = n*(n+1)/2;
rep(i,0,x-1)
{
ans.zs += f[n+1][0][i]*x/(x-i);
change(ans,f[n+1][0][i]*x,x-i);
tmp.zs += f[n+1][1][i]*x/(x-i);
change(tmp,f[n+1][1][i]*x,x-i);
}
del();
ans.xs[15] += ans.xs[16] >= 5 ? 1 : 0;
repp(i,15,1) ans.xs[i-1] += ans.xs[i] / 10,ans.xs[i] %= 10;
ans.zs += ans.xs[0];
printf("%lld.",ans.zs);
rep(i,1,15) printf("%d",ans.xs[i]);printf("\n");
}
return 0;
}