Źródło: Google Code Jam. https://code.google.com/codejam/contest/10224486/dashboard#s=a&a=1Praca z małymi prawdopodobieństwami, za pomocą dzienników
Jesteśmy proszeni o obliczenie Prob (sukcesy K z testów N), gdzie każde z N prób ma znane prawdopodobieństwo sukcesu p_n.
Niektóre analizy i przemyślenia na temat problemu są podawane po wystąpieniu zakleszczenia kodu.
Zauważają, że ocena wszystkich możliwych wyników twoich N testów zajęłaby ci wykładniczy czas w N, więc zamiast tego dostarczają fajne "styl programowania dynamicznego", czyli O (N^2).
Niech P (p # q) = prob (Sukcesy p Po pierwsze próby q) Następnie zaobserwować fakt, że:
Prob(p#q) = Prob(qth trial succeeds)*P(p-1#q-1) + Prob(qth trial fails)*P(p#q-1)
Teraz budujemy tabelę P (I # j) gdzie i < = j, dla i = 1 ... N
To wszystko piękne - podążam za tym wszystkim i mogę je wdrożyć.
Następnie jako ostatni komentarz, mówią:
In practice, in problems like this, one should store the logarithms of
probabilities instead of the actual values, which can become small
enough for floating-point precision errors to matter.
myślę szeroko zrozumieć punkt Próbują zrobić, ale konkretnie nie może dowiedzieć się, jak wykorzystać tę sugestię .
Biorąc powyższe równanie, a substuting w niektórych literach zmienne:
P = A*B + C*D
Jeśli chcemy pracować w obszaru dziennika, wtedy mamy:
Log(P) = Log(A*B + C*D),
gdzie mamy rekurencyjnie wstępnie obliczane Log(B)
i Log(D)
i A
& to znane, łatwe w obsłudze miejsca dziesiętne.
Ale nie widzę sposobu, aby obliczyć Log(P)
, nie robiąc po prostu e^(Log(B))
, itp., Co wydaje się, że pokona punkt pracy w przestrzeni dziennika "?
Czy ktoś rozumie bardziej szczegółowo, co mam robić?
oooh !!! Tak, oczywiście. Dziękuję bardzo jasne wyjaśnienie tego procesu. Wielkie dzięki! – Brondahl
Powitanie :) wyjaśnienie problemu było również bardzo jasne! (inaczej, gdybym tylko zobaczył uwagę z zacięcia kodu, nie jestem pewien, czy zrozumiałbym takie podejście). – qwertyman