假设我们有一个整数 N
. 在每个 K
试验中,该数字从均匀区间中减去一个随机整数 [0, M]
(所以如果我们 M = 5
,然后是一个数字 N
在每一次试验中 0
, 1
, 2
, 3
, 4
或者 5
,每个都有一个概率 1/6
). 这个数字 N
之后将小于或等于零 K
审判?例如 N=2
, M=1
以及 K=3
答案是 0.5
.
我可以写一个暴力解决方案,简单地枚举每一个置换的总数 (M+1)^K
并在 N
最终成为 <= 0
在给定的排列中减去所有的数。但对于这个问题, M
以及 K
可能高达1000,然后这种复杂性就变得 1000^(1000)
这是棘手的。
所以我想知道是否有一些数学公式可以帮助我避免产生所有的排列?
2条答案
按热度按时间7xllpg7q1#
我将只在这里集中在算法层面。
该问题等价于计算出比k步后的概率,其值之和大于n。
让我们打电话
p
在给定的一步中,元素被选中的概率其思想是以多项式形式表示一次试验的概率集:
之后
K
步骤,概率集由下式给出:最后,如果
F[x] = sum_i p_i x^i
,则概率为:问题是如何计算多项式的幂
A[x]^k
.第一次尝试考虑递归地计算它:然后我们得到了与第一个答案中提供的解等价的东西,同样的复杂性。
第二个尝试是隐式地考虑
K
.伪代码:
步数等于
log2(K)
.在每次迭代中,多项式的次数乘以2:复杂度由最后一步决定,其中多项式的阶数等于
KM
.最后一步很复杂
O(K^2 M^2)
.如果
C = K^2 M^2
,功率计算的全局复杂性为O(C + C/4 + C/8 + ...) = O(C) = O(K^2M^2)
.与第一种方法相比,这种方法似乎没有任何优势(我可能在复杂性评估中出错了!)。
第三种方法在于考虑多项式乘法等效于卷积,并且可以通过fft过程来执行。由于最终尺寸为o(km),则复杂性为
O(M K (log M + log K))
.在这里详细描述这个方法会花费很多时间。你可以在网上找到许多关于这个问题的参考资料,例如这里
旁注:很遗憾不能在这里插入乳胶数学公式。。。
up9lanfz2#
这是一个计算所需概率的程序
工作代码链接
在这里,我们跟踪集合的计数,这些集合相加到给定的和
count[]
数组任何加起来大于
N
已添加到count[N]
这是怎么回事?起初,
count[0] = 1
,因为我们只有空集{}
(k=1):尝试向所有现有集添加一个元素:{} + 0, {} + 1
. 我们得到{0}, {1}
所以呢count[0] = 1
,count[1] = 1
(k=2):现在再次向所有现有集合添加一个元素:{0} + 0, {0} + 1, {1} + 0, {1} + 1
. 我们得到{0,0},{0,1},{1,0},{1,1}
所以呢count[0] = 1
,count[1] = 2
,count[2] = 1
(k=3):现在再次向所有现有集合添加一个元素。我们会得到{0,0,0}, {0,0,1}, {0,1,0}, {1,0,0}, {0, 1, 1}, {1, 0, 1}, {1,1,0}, {1,1,1}
. 所以呢count[0] = 1
,count[1] = 3
,count[2] = 4
在最后一步中,我们还添加了{1,1,1}
至count[2]
因为我们加上所有和为>= N
至count[N]
最后,我们来计算概率count[N]
(总数为>=N
)所有可能集合的计数,即,(M+1)^K
复杂性是O(N*M*K)
. 在最坏的情况下N=M*K
,因此时间复杂度可以重写为:O((M*K)^2)
优化1:如果你写下
count[]
每次迭代的数组K
你可以发现一个有趣的观察结果:这里的观察是:
通过保持以前m值的滚动总和,我们可以编写优化版本的代码:
工作代码链接
这种方法的时间复杂性是
O(M*(K^2))