Очікувана мінімальна степінь#11262

Очікувана мінімальна степінь (Розбір)

Вибрати різних цілих чисел із можна C_n^x способами.

Розглянемо, скільки існує підмножин із чисел, мінімальним елементом у яких є число . Для цього в підмножину обов'язково включається число , а також обираються ще x - 1 чисел, кожне з яких строго більше . Чисел, більших від , всього n - i, і обрати з них x - 1 число можна C_{n-i}^{x-1} способами.

Зазначимо також, що повинно виконуватися нерівність i + x - 1 \le n, оскільки інакше неможливо обрати x - 1 чисел, більших від . Звідси слідує обмеження i \le n - x + 1.

Щоб обчислити очікуване значення величини 2^S, необхідно знайти середньозважене значення цієї величини по всіх можливих підмножинах:

\frac{\sum_{i = 1}^n 2^i \cdot C_{n - i}^{x - 1}}{C^x_n} = \frac{\sum_{i = 1}^{n - x + 1} 2^i \cdot C_{n - i}^{x - 1}}{C^x_n}

Якщо i > n - x + 1, то кількість відповідних підмножин вважається рівним нулю.

Приклад

У першому тесті можливий єдиний варіант вибору: \{1, 2, 3, 4\}. Мінімальним елементом є число , тому шукане значення дорівнює 2^1 = 2.

У другому тесті існує три рівноймовірних варіанти: , і . Відповідні значення рівні , і . Тоді середнє значення величини 2^S дорівнює

(2^1 + 2^1 + 2^2) / 3 = 8 / 3 = 2.6666666

Обчислимо вказану відповідь за формулою:

\frac{\sum_{i = 1}^n 2^i \cdot C_{n - i}^{x - 1}}{C^x_n} = \frac{2^1 \cdot C_2^1 + 2^2 \cdot C_1^1}{C^2_3} = \frac{2 \cdot 2 + 4 \cdot 1}{3} = \frac{8}{3}

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

Функція Cnk обчислює значення біноміального коефіцієнта C_n^k. Значення біноміальних коефіцієнтів будемо зберігати в осередках масиву .

long long dp[51][51];

long long Cnk(int n, int k)
{
  if (n == k) return 1;
  if (k == 0) return 1;
  if (dp[n][k] != -1) return dp[n][k];
  return dp[n][k] = Cnk(n - 1, k - 1) + Cnk(n - 1, k);
}

Основна частина програми.

scanf("%d %d", &n, &x);
memset(dp, -1, sizeof(dp));

Вичислюємо відповідь: \frac{\sum_{i = 1}^{n - x + 1} 2^i \cdot C_{n - i}^{x - 1}}{C^x_n}.

a = 0;
for (i = 1; i <= n - x + 1; i++)
   a = a + Cnk(n - i, x - 1) * (1LL << i);
res = 1.0 * a / Cnk(n, x);

Виводимо відповідь.

printf("%lf\n", res);