Однакові кулі#1316

Однакові кулі (Розбір)

Обчислимо ймовірність протилежної події — того, що останніми будуть вийняті кульки різного кольору. Для цього серед перших n - 2 вийнятих кульок рівно половина має бути білими, а половина — чорними.

Розглянемо схему випробувань Бернуллі, де ймовірність успіху (наприклад, появи білої кульки) дорівнює p = 1/2, а неуспіху q = 1 - p = 1/2. Ймовірність того, що серед n - 2 вийнятих кульок виявиться рівно (n - 2) / 2 білих, обчислюється за формулою:

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}

Залишається для кожного вхідного обчислити значення і вивести 1 - P(X).

Хоча знаходиться в межах від до включно, його безпосереднє обчислення може призвести до числових проблем. Щоб уникнути цього, обчислимо логарифм:

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

Після обчислення правої частини рівності піднесемо до отриманого значення, щоб відновити . Логарифм факторіала обчислимо як суму логарифмів:

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

Оскільки на вхід програми подається декілька тестів, усі відповіді слід попередньо обчислити і зберегти в масиві.

Приклад

Для n = 6 ймовірність того, що останніми будуть вийняті кульки різного кольору, дорівнює

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

Ймовірність того, що останніми будуть вийняті кульки одного кольору, дорівнює

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

Реалізація алгоритму

Оголосимо необхідні масиви. У комірці будемо зберігати значення C_{i-2}^{i/2-1} p^{i/2 - 1} q^{i/2 - 1}.

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

Заповнимо масив , де зберігає значення .

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

Для кожного значення обчислимо ln~C_{i-2}^{i/2-1} p^{i/2 - 1} q^{i/2 - 1} і збережемо результат в .

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

Для кожного вхідного значення обчислюємо і виводимо відповідь.

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