我有机会赢得大奖吗?


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条生命的人数。此号码始终包含您。

因此,如果我有一个函数pp(10, 5),这就是赢得奖金的概率,总共有10个人,其中5个人只有1人生,而5(包括您)有2人生。


您应该输出准确或十进制形式获胜的概率。无论如何,答案必须精确到小数点后第四,包括小数点后第四。是否舍入到该数字取决于您。

您的解决方案可以是随机化的溶液,其输出的答案为4 与小数位高概率。您可能会假设您使用的内置RNG确实是随机的,并且它必须以至少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
贾斯汀(Justin)

因此,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 ...
Leaky Nun

@KennyLau我不会尝试去解释它,但是要当心math.se链接,因为它使用的函数定义略有不同(我相信这k是个错误)
Justin

2
是否可以进行足够的试验来进行随机模拟,以使答案很有可能正确地排在小数点后第四位,尽管当然不能确定?
xnor

Answers:


2

MATL,42字节

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

这使用概率(Monte Carlo)方法。实验进行了很多次,从中可以估算出概率。选择实现的数量以确保结果正确无误,直到第四个小数点为止,概率至少为90%。但是,这需要很长的时间和大量的内存。在下面的链接中,实现的数量减少了10 6倍,以便该程序在合理的时间内结束。并且只有第一个小数点被保证具有至少90%的概率是准确的。

编辑(2016年7月29日):由于语言更改,6L需要替换为3L。下面的链接包含了该修改。

在线尝试!

背景

p表示要计算的概率。挑战中描述的实验将运行n次。每次,您要么赢得奖(“ 成功 ”),要么就没有。令N为成功次数。可以从Nn 估计所需概率。n越大,估计将越准确。关键问题是如何选择n以实现所需的精度,即确保至少90%的误差小于10 -4

蒙特卡洛方法可以是

  • 固定大小n的值是预先固定的(然后N是随机的);
  • 可变大小n由仿真结果动态确定。

在第二类中,一种常用的方法是修复N(所需的成功次数)并不断进行模拟,直到获得该成功次数为止。因此,n是随机的。这项技术称为逆二项式采样负二项式蒙特卡洛,其优点是可以限制估计器的精度。因此,将在这里使用它。

具体而言,对于负二项式蒙特卡洛,x =(N -1)/(n -1)是p的无偏估计;并且x偏离p超过给定比率的概率可以是上限。根据等式(1)本文(还要注意,条件(2)被满足),取ñ = 2.75·10个8或更大确保p / X属于区间[1.0001,0.9999]具有至少90%的可能性。特别是,这意味着x可以根据需要以至少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

测试套件

定义确定性memoized递归函数gñķ作为参数。 g 1000 5000.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)也要花费大量时间。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.