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