Какова вероятность, что я выиграю дверной приз?

12

Моя местная глава ACM раздает дверные призы людям, которые приходят на собрания. Однако вы получите больше шансов на победу, если решите головоломку программирования (но я всегда решаю эту головоломку). Таким образом, некоторые люди имеют 1 запись, а другие - 2. Но подождите! Программа лотереи работает не путем добавления другой записи, когда кто-то решает головоломку. Вместо этого он отслеживает количество «жизней» человека, уменьшая его, если этот человек выбирается на каждом проходе алгоритма случайной выборки. Так что это работает так:

Doorknob: 1.  xnor: 2.  Justin: 2.  Alex: 1.  Dennis: 2.

Затем программа случайным образом выбирает одно из значений [Doorknob, xnor, Justin, Alex, Dennis], уменьшает число (скажем, выбирает Justin):

Doorknob: 1.  xnor: 2.  Justin: 1.  Alex: 1. Dennis: 2.

И повторяется. Если чье-то количество «жизней» перейдет к 0(давайте выберем Justinснова), они будут удалены из списка:

Doorknob: 1.  xnor: 2.  Alex: 1.  Dennis: 2.

Это продолжается до тех пор, пока не останется один человек; этот человек является победителем.

Теперь реальный вопрос, какова вероятность того, что я бы выиграл?


Вам будут предоставлены два входа:

  • n, Это количество людей, вступивших в вызов
  • k, Это количество людей (из тех n), которые имеют 2 жизни. Этот номер всегда включает вас.

Так что, если бы у меня была функция pи позвонил p(10, 5), это было бы вероятностью выиграть приз, если всего 10 человек, 5 из которых имеют только 1 жизнь, тогда как 5 (включая вас) имеют 2 жизни.


Ожидается, что вы получите вероятность выигрыша либо точно, либо в виде десятичной дроби. Во всяком случае, ответы должны быть с точностью до и в том числе 4 - го знака после запятой после десятичной точки. Независимо от того, округлили ли вы эту цифру или нет, зависит от вас.

Ваше решение может быть рандомизированным решением, которое с высокой вероятностью выводит ответ с точностью до 4- го знака после запятой . Вы можете предположить, что используемая вами встроенная ГСЧ действительно случайная, и она должна вывести правильный ответ с вероятностью не менее 90%.

Кроме того, ваш код должен работать только для n, k <= 1000, хотя я предоставил тестовые примеры больше, чем для любопытных.


Тестовые случаи

Примечание: некоторые из них являются общими формулами.

n,    k   |  output
----------+---------
1,    1   |  1
2,    2   |  0.5
2,    1   |  0.75
3,    1   |  11/18 = 0.611111111
1000, 1   |  0.007485470860550352
4,    3   |  0.3052662037037037
k,    k   |  1/k
n,    1   |  (EulerGamma + PolyGamma[1 + n])/n    (* Mathematica code *)
          |  (γ + ψ(1 + n))/n
10,   6   |  0.14424629234373537
300,  100 |  0.007871966408910648
500,  200 |  0.004218184180294532
1000, 500 |  0.0018008560286627948
---------------------------------- Extra (not needed to be a valid answer)
5000, 601 |  0.0009518052922680399
5000, 901 |  0.0007632938197806958

Для еще нескольких проверок сделайте p(n, 1) * nследующее:

n     |  output
------+---------
1     | 1
2     | 1.5 
3     | 1.8333333333333335
10    | 2.928968253968254
100   | 5.1873775176396215
-------------------------- Extra (not needed to be a valid answer)
100000| 12.090146129863305
Джастин
источник
Я больше не знаком с тегами на этом сайте; если вы думаете о более подходящем теге, отредактируйте его!
Джастин
Тесно связанный вопрос на math.se: math.stackexchange.com/q/1669715/72616
Джастин
Итак, P (n, k) = ((k-1) / n) P (n, k-1) + ((nk) / n) P (n-1, k) + (1 / n) Q ( n, k-1), где Q (n, k) = ((nk-1) / n) Q (n-1, k) + (k / n) Q (n, k-1) и Q (1 , 0) = 1 ...
Утренняя монахиня
@KennyLau Я не собираюсь пытаться интерпретировать это, но остерегайтесь ссылки math.se, так как она использует немного другое определение функции (я думаю, kона отключена одним)
Джастин
2
Можно ли проводить рандомизированное моделирование с достаточным количеством испытаний, чтобы ответ был верным с точностью до четвертого знака после запятой с большой вероятностью, хотя, конечно, нет уверенности?
xnor

Ответы:

2

MATL , 42 байта

:<~QXJx`J`tf1Zry0*1b(-tzq]f1=vts3e8<]6L)Ym

Это использует вероятностный (Монте-Карло) подход. Эксперимент проводится большое количество раз, из которых оценивается вероятность. Число реализаций выбирают так, чтобы гарантировать , что результат является правильным до четвертого знака после запятой с вероятностью не менее 90%. Однако это занимает очень много времени и много памяти. В приведенной ниже ссылке количество реализаций было сокращено в 10 6 раз, так что программа заканчивается в разумные сроки; и только первый десятичный знак гарантированно будет точным с вероятностью не менее 90%.

РЕДАКТИРОВАТЬ (29 июля 2016 г.): в связи с изменением языка 6Lнеобходимо заменить на 3L. Ссылка ниже включает эту модификацию.

Попробуйте онлайн!

Фон

Пусть p обозначает вероятность, которую нужно вычислить. Эксперимент, описанный в задании, будет проводиться несколько раз n . Каждый раз либо вы выигрываете приз (« успех »), либо нет. Пусть N будет количеством успехов. Желаемая вероятность может быть оценена из N и n . Чем больше n , тем точнее будет оценка. Ключевой вопрос заключается в том, как выбрать n для выполнения с желаемой точностью, а именно, чтобы гарантировать, что по крайней мере в 90% случаев ошибка будет меньше 10 -4 .

Методы Монте-Карло могут быть

  • Фиксированный размер : значение n фиксируется заранее (а затем N является случайным);
  • Переменный размер : n определяется на лету по результатам моделирования.

Среди второй категории обычно используемый метод состоит в том, чтобы фиксировать N (желаемое количество успехов) и продолжать моделирование до тех пор, пока не будет достигнуто это количество успехов . Таким образом, n является случайным. Эта методика, называемая обратной биномиальной выборкой или отрицательной биномиальной Монте-Карло , имеет то преимущество, что точность оценки может быть ограничена. По этой причине он будет использован здесь.

В частности, с отрицательным биномиальным множителем Монте-Карло x = ( N −1) / ( n −1) является несмещенной оценкой p ; и вероятность того, что x отклонится от p более чем на заданное соотношение, может быть ограничена сверху. В соответствии с уравнением (1) в этой статье (обратите внимание также, что условия (2) выполняются), принимая N = 2,75 · 10 8 или более, гарантирует, что p / x принадлежит интервалу [1.0001, 0.9999] по меньшей мере на 90% вероятность. В частности, это означает, что x является правильным с точностью до 4-го знака после запятой с вероятностью не менее 90%, как желательно.

Код объяснил

Код использует N = 3e8для сохранения одного байта. Обратите внимание, что выполнение этого большого количества симуляций заняло бы много времени. Код в ссылке использует N = 300, который выполняется в более разумное время (менее 1 минуты в онлайн-компиляторе для первых тестовых случаев); но это только гарантирует, что первое десятичное число является правильным с вероятностью не менее 90%.

:        % Take k implicitly. Range [1 ... k]
<~       % Take n implicitly. Determine if each element in the previous array is
         % less than or equal than n
Q        % Add 1. This gives an array [2 ... 2 1 ... 1]
XJx      % Copy to clipboard J. Delete from stack
`        % Do...while. Each iteration is a Monte Carlo realization, until the 
         % desired nunber of successes is reached
  J      %   Push previously computed array [2 ... 2 1 ... 1]
  `      %   Do...while. Each iteration picks one door and decrements it, until
         %   there is only one
    t    %     Duplicate
    f    %     Indices of non-zero elements of array
    1Zr  %     Choose one of them randomly with uniform distribution
    y0*  %     Copy of array with all values set to 0
    1b(  %     Assign 1 to chosen index
    -    %     Subtract
    tzq  %     Duplicate. Number of nonzero elements minus 1. This is falsy if
         %     there was only one nonzero value; in this case the loop is exited
  ]      %   End do...while
  f1=    %   Index of chosen door. True if it was 1 (success), 0 otherwise
  v      %   Concatenate vertically to results from previous realizations
  ts3e8< %   Duplicate. Is the sum less than 3e8? If so, the loop is exited
]        % End do...while
6L)      % Remove last value (which is always 1)
Ym       % Compute mean. This gives (N-1)/(n-1). Implicitly display
Луис Мендо
источник
Хаха, я не осознавал, что 90% затруднят это :-)
Джастин
Да, четвертое десятичное число с уверенностью в 90% - это действительно сильное требование :-)
Луис Мендо
2

Pyth, 34 байта

Mc|!*HJ-GHch*J+*tHgGtH*gtGHKh-GHKG

Тестирование

Определяет детерминированную запомненную рекурсивную функцию, gпринимающую n , k в качестве аргументов. g 1000 500возвращает 0.0018008560286627952примерно через 18 секунд (не входит в вышеуказанный набор тестов, потому что истекает время онлайн-переводчика).

Примерный перевод Python 3 будет

@memoized
def g(n,k):
    return (not k*(n-k) or (1+(n-k)*((k-1)*g(n,k-1)+g(n-1,k)*(n-k+1)))/(n-k+1))/n
Андерс Касеорг
источник
1

JavaScript (ES6), 65 байт

f=(n,k,d=n-k)=>(!d||(f(n-1,k)*++d*--d+1+(--k&&f(n,k)*k*d))/++d)/n

Не пытайтесь сделать это с большими числами; даже f (30, 10) занимает заметное количество времени.

Нил
источник