Aladdin and the Magical Sticks LightOJ - 1342
有两种棍子,一种摸过之后就可以辨别,另外一种无法辨别,总共有 n n n 个棍子,每次从中间摸一个出来,假如每个棍子都摸出来过,那么结束,否则该棍子仍然要放回去进行下一轮操作。对于摸过一次后就可以辨别的棍子类型,之后选择都不再摸,也就是说,设可以选择的棍子集合为 A \mathcal{A} A,第一次从中等概率地摸一个棍子 i i i ,假如是可辩别的,那么把这个棍子踢出棍子集合,即 A ← A / i \mathcal{A}\gets \mathcal{A}/i A←A/i ,然后在新的集合 A \mathcal{A} A 中重新进行上述操作,直到所有棍子都被摸过至少一次;假如不可辨别,那么集合 A \mathcal{A} A 不变,重新操作。
每个棍子都有对应的重量 w i w_i wi,问操作结束时摸过的棍子的重量期望是多少?
类似 邮票收集问题
假如所有的棍子都是不可辨别的,先假设重量都是 1 1 1 的话,那么总的期望应该是 n ⋅ H n n\cdot H_n n⋅Hn,其中 H n = ∑ i = 1 n 1 i H_n=\sum_{i=1}^n{\frac{1}{i}} Hn=∑i=1ni1,平均下来一个不可辨别的棍子对应的期望是 H n H_n Hn,而对于可辨别的棍子来说,他们的期望都是 1 1 1,所以分开计算即可。
(但是其实上面这个平均操作我觉得并不能从直观意义上进行理解,具体可以看看 Wikipedia 的推导过程就可以感受得到)
代码如下:
#include<iostream>
#include<cstdio>
//#define WINE
using namespace std;
int T,iCase,n,a,b;
double res,H[5506];
int main(){
#ifdef WINE
freopen("data.in","r",stdin);
#endif
for(int i=1;i<=5005;i++)
H[i]=H[i-1]+1.0/i;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
res=0;
for(int i=0;i<n;i++){
scanf("%d%d",&a,&b);
if(b==1)res+=a;
else res+=a*H[n];
}
printf("Case %d: %.8lf\n",++iCase,res);
}
return 0;
}