問題
カードC, M, Pが確率c, m, pで配られる
それ以外のパラメータvがある
Pを引いたらゲームは終わり
C, Mを引いたら確率が変化する。ここではCを引いたとする
c<=vならc=0となり、c=invalidとなる。cの値は他のvalidな確率に分配される
c>vならc-=vとなり、減った分の確率vは他のvalidな確率に分配される
引く回数の期待値を求めよ
解説
- 「c, mがどんどん減っていく」かつ「v>=0.1」なので、少ない回数で収束する
- 再帰関数を書けばいい
- 誤差に注意
誤差がどうWAになるか
- 0と判定すべき時に誤差で0と判定できなかった場合、確率の分配の割り振り対象となってしまい、シミュレーションが狂う
誤差を切り抜ける方法
using ld = long double;
constexpr ld EPS = 1e-14;
constexpr bool equals(ld a, ld b){return fabs((a)-(b)) < EPS;}
提出
code
ld f(ld c, ld m, ld p, ld v){
ld exp=0;
if(c>EPS){
if(c<=v){
if(m>EPS){
exp += c * (1+f(0,m+c/2,p+c/2,v));
}else{
exp += c * (1+f(0,0,1,v));
}
}
else{
if(m>EPS){
exp += c * (1+f(c-v,m+v/2,p+v/2,v));
}else{
exp += c * (1+f(c-v,0,p+v,v));
}
}
}
if(m>EPS){
if(m<=v){
if(c>EPS){
exp += m * (1+f(c+m/2,0,p+m/2,v));
}else{
exp += m * (1+f(0,0,1,v));
}
}
else{
if(c>EPS){
exp += m * (1+f(c+v/2,m-v,p+v/2,v));
}else{
exp += m * (1+f(0,m-v,p+v,v));
}
}
}
exp += p;
return exp;
}
void solve(){
ld c,m,p,v;
cin>>c>>m>>p>>v;
ld ans = f(c,m,p,v);
cout<<setprecision(20);
p(ans);
}
int main(){
cin.tie(0);
ios::sync_with_stdio(false);
ll N;
cin>>N;
while(N--)solve();
return 0;
}