難易度Blue 350 (非公式難易度表)
「k回の睡眠でR=r, L=lとした時のPP」を返す関数retを考えて、深さ優先探索を行う発想は自然。
だが、これだけでは2^30で計算が間に合わない。
なので、l, rとP, Eの関係に枝刈り条件を加える。
ret内のl-rを呼び出し回数に関して指数関数的に収束させていくので、この条件はかなり強い枝刈りが可能である。
#include <iostream>
#include <cstdio>
using namespace std;
#define abs(a) ((a) > 0 ? (a) : -(a))
double P, E, T;
double ret(double k, double r, double l)
{
double h = (r + l) / 2;
if (k == 0)
return (abs(h-T) < E ? 1.0 : 0.0);
if (l < T - E)
return 0.0;
if (r > T + E)
return 0.0;
if (T - E < r && l < T + E)
return 1.0;
if ((r+l)/2 >= T)
return P * ret(k-1, r, h) + (1.0 - P) * ret(k-1, h, l);
else
return P * ret(k-1, h, l) + (1.0 - P) * ret(k-1, r, h);
}
int main(void)
{
double K, R, L;
cin >> K >> R >> L >> P >> E >> T;
P = 1 - P;
printf("%.6f", ret(K, R, L));
return 0;
}