Palline identiche#1316

Palline identiche (Editoriale)

Calcoliamo la probabilità dell'evento opposto — ovvero che le ultime palline estratte siano di colore diverso. Per questo, tra le prime n - 2 palline estratte, esattamente la metà deve essere bianca e la metà nera.

Consideriamo uno schema di prove di Bernoulli, dove la probabilità di successo (ad esempio, l'apparizione di una pallina bianca) è uguale a p = 1/2, e di insuccesso q = 1 - p = 1/2. La probabilità che tra le n - 2 palline estratte risultino esattamente (n - 2) / 2 bianche, si calcola con la formula:

P(X) = C_{n-2}^{n/2-1} p^{n/2 - 1} q^{n/2 - 1} = {(n - 2)! \over \left(\left({n \over 2} - 1\right)!\right)^2} \left({1 \over 2}\right) ^ {n - 2}

Resta, per ogni in ingresso, calcolare il valore e stampare 1 - P(X).

Sebbene sia compreso tra e inclusi, il suo calcolo diretto può portare a problemi numerici. Per evitarlo, calcoliamo il logaritmo:

ln P(X) = ln(n - 2)! - 2 \cdot ln\left({n \over 2} - 1 \right)! - (n - 2) \cdot ln~2

Dopo aver calcolato il lato destro dell'uguaglianza, eleviamo al valore ottenuto per ricostruire . Il logaritmo del fattoriale lo calcoleremo come somma di logaritmi:

ln~n! = ln~1 + ln~2 + ln~3 + ... + ln~n

Poiché in ingresso al programma vengono forniti più test, tutte le risposte devono essere precalcolate e memorizzate in un array.

Esempio

Per n = 6 la probabilità che le ultime palline estratte siano di colore diverso è uguale a

C_4^2~p^2q^2 = 6 \cdot \left({1 \over 2} \right)^4 = {6 \over 16} = {3 \over 8}

La probabilità che le ultime palline estratte siano dello stesso colore è uguale a

1 – {3 \over 8} = {5 \over 8} = 0,625

Implementazione dell'algoritmo

Dichiariamo gli array necessari. Nella cella memorizzeremo il valore C_{i-2}^{i/2-1} p^{i/2 - 1} q^{i/2 - 1}.

#define MAX 100001
double lf[MAX], ans[MAX];

Riempiamo l'array , dove memorizza il valore .

res = lf[1] = 0.0;
for (res = 0, i = 2; i < MAX; i++)
{
  res += log((double)i);
  lf[i] = res;
}

Per ogni valore calcoliamo ln~C_{i-2}^{i/2-1} p^{i/2 - 1} q^{i/2 - 1} e memorizziamo il risultato in .

for (i = 2; i < MAX; i += 2)
{
  res = lf[i/2-1];
  res = lf[i-2] - (i - 2) * log(2.0) – res - res;
  ans[i] = exp(res);    
}

Per ogni valore in ingresso calcoliamo e stampiamo la risposta.

while (scanf("%d",&n) == 1)
  printf("%.8lf\n",1 - ans[n]);