Algorithm 表达式的期望值
如何在Algorithm 表达式的期望值,algorithm,math,Algorithm,Math,如何在p/Q 给定: N个整数 2个运算符,“按位或”&“+” 我们可以使用两个运算符中的任意一个,每个连续整数之间的概率相等,以形成表达式 目前,我想到的解决方案是使用运算符生成所有可能的表达式,然后使用每个表达式的值计算出它的预期值 但随着N的增长,这种方法失败了。在时间复杂度方面是否有其他有效的替代方案 注意:对于这个问题:“按位或”的优先级高于“+”运算符 最多可以有10^5个整数 例如: Input 1 2 3 Output 19/4 不同的方法是: 1+2+3 = 6 1+2|
p/Q
给定:N个整数
2个运算符,“按位或”&“+” 我们可以使用两个运算符中的任意一个,每个连续整数之间的概率相等,以形成表达式 目前,我想到的解决方案是使用运算符生成所有可能的表达式,然后使用每个表达式的值计算出它的预期值 但随着N的增长,这种方法失败了。在时间复杂度方面是否有其他有效的替代方案 注意:对于这个问题:“按位或”的优先级高于“+”运算符 最多可以有10^5个整数 例如:
Input
1 2 3
Output
19/4
不同的方法是:
1+2+3 = 6
1+2|3 = 4
1|2+3 = 6
1|2|3 = 3
所有这些方法都有概率=1/4
因此,预期值将为
19/4
重要的观察结果是,每个+
都将其左右部分分割为可以独立处理的部分
让数字数组为a[1…N]
。将f(i)
定义为从a[i…N]
获得的期望值。我们想要找到的是f(1)
请注意,第一个+
登录[i…N]
将出现在概率1/2的i
th元素和概率1/4的i+1
th元素之后,依此类推。只需按位查找元素的or,直到+
,然后添加剩余元素的期望值
这样我们就有了复发
f(i)=和{j=i到N-1}(或(a[i…j])+f(j+1))/(2^(j-i+1))
+或(a[i…N])/(2^(N-i))
这应该很容易实现,而且没有错误
对于示例数组[1,2,3]
:
- f(3)=或(a[3…3])=3
- f(2)=(或(a[2…2])+f(3))/2+或(a[2…3])/2=5/2+3/2=4
- f(1)=(或(a[1…1])+f(2))/2+(或(a[1…2])+f(3))/4+或(a[1…3])/4=5/2+6/4+3/4=19/4
答案是19/4,正如预期的那样。首先,因为有2ⁿ⁻1
表达式(数字之间的n-1
位置上各有两个可能的运算符),并且它们的概率都相等,期望值是所有表达式之和除以2ⁿ⁻CharStyle
。所以问题归结为计算表达式的和
一种O(n²)
算法
让x_1,x_2,…,x_n
作为输入数字
设suk
为通过在列表x_1,x_2,…,x_k
中的每对连续数字之间插入
或+
而形成的所有表达式的总和
设N_k
为所有此类表达式的数目<代码>N_k=2^(k-1)
让我们看看如何使用s_1,s_2,…,s_(k-1)
来计算s_k
其思想是将所有可能的表达式除以最后一个“+”
表达式的位置
“…+x_k”
形式的表达式之和为
S_k(k-1)+x_k*N_k(k-1)
“..+x_k(k-1)|x_k”
形式的表达式之和为
S_uk(k-2)+(x_k(k-1)| x_k)*N_k(k-2)
“..+x_uUk(k-2)|x_Uk(k-1)|x_k”
形式的表达式之和为
S_uk(k-2)+(x_uk(k-2)| x_uk(k-1)| x_k)*N_uk(k-3)
…依此类推,直到单个表达式x|u 1 | x|u 2 |…|x_k
下面是该算法的Python实现
numbers = [1, 2, 3] # The input numbers.
totals = [0] # The partial sums. For every k > 0 totals[k] is S_k.
for i in range(len(numbers)): # Processing the numbers one by one.
new_total = 0
last_summand = 0 # last_summand is numbers[j] | ... | numbers[i]
for j in range(i, 0, -1): # j is the position of the last plus in the expression.
# On every iteration new_total is increased by the sum of the
# expressions of the form "... + numbers[j] | ... | numbers[i]".
last_summand |= numbers[j]
new_total += totals[j] + last_summand * (2 ** (j - 1))
last_summand |= numbers[0]
new_total += last_summand # Handling the expression with no pluses at all.
totals.append(new_total)
# Now the last element in totals is the sum of all expressions.
print(str(totals[-1]) + '/' + str(2**(len(numbers) - 1)))
进一步优化:O(n*log(M))
该问题有两个属性,可用于创建更快的算法
numbers = [1, 2, 3] # The input numbers.
totals = [0] # The partial sums. For every k > 0 totals[k] is S_k.
for i in range(len(numbers)): # Processing the numbers one by one.
new_total = 0
last_summand = 0 # last_summand is numbers[j] | ... | numbers[i]
for j in range(i, 0, -1): # j is the position of the last plus in the expression.
# On every iteration new_total is increased by the sum of the
# expressions of the form "... + numbers[j] | ... | numbers[i]".
last_summand |= numbers[j]
new_total += totals[j] + last_summand * (2 ** (j - 1))
last_summand |= numbers[0]
new_total += last_summand # Handling the expression with no pluses at all.
totals.append(new_total)
# Now the last element in totals is the sum of all expressions.
print(str(totals[-1]) + '/' + str(2**(len(numbers) - 1)))
如果S_n
是由数字x_1,x_2,…,x_n
构成的表达式之和,则2*S_n
是由数字2*x_1,2*x_2,…,2*x_n
构成的表达式之和
如果x_1,x_2,…,x_n
和y_1,y_2,…,y_n
对于任何k
和m
,x_n
是由x_1,x_2,…,x_n
形成的表达式之和,SY u n
是由y,y,u,n>形成的表达式之和,然后,SX_n+SY_n
是由x_1+y_1,x_2+y_2,…,x_n+y_n
形成的表达式之和
这意味着,问题可以简化为寻找1位数字的表达式之和。从0
到31
的每个位位置都可以单独处理,找到解决方案后,我们可以简单地添加它们
设x_1,x_2,…,x_n
为一位数字(每个x_i
为0
或1
)
设suk
为x_1,x_2,…,x_k
形成的表达式之和
设N0_k
为此类表达式的数目,其中最后的和等于0
设N1_k
为此类表达式的数目,其中最后的和等于1
这里是允许查找S_k
、N0_k
和N1_k
只知道x_k
、S_k(k-1)
、N0_k(k-1)
和N1_k(k-1)
:
k=1,x_=0
:
S_1=0
N0\u 1=1
N1_1=0
k=1,x_=1
:
S_1=1
N0\u 1=0
N1_1=1
k>1,x_k=0
:
S_k=S_k(k-1)*2
N0_k=N0_(k-1)*2+N0_(k-1)
N1_k=N1_(k-1)
k>1,x_k=1
:
S_k=S_(k-1)*2+N0_(k-1)*2+N0_(k-1)
N0\u k=0
N1\k