所有长度为 k 的子数组的元素的乘积之和

Posted

技术标签:

【中文标题】所有长度为 k 的子数组的元素的乘积之和【英文标题】:Sum of products of elements of all subarrays of length k 【发布时间】:2016-01-01 23:58:20 【问题描述】:

给出一个长度为 n 的数组。求子数组元素的乘积之和。

说明

数组 A = [2, 3, 4],长度为 3

子数组长度2 = [2,3], [3,4], [2,4]

[2, 3] = 6

中元素的乘积

[3, 4] = 12

中元素的乘积

[2, 4] = 8

中元素的乘积

长度为2 = 6+12+8 = 26的子数组的总和

同样,对于长度 3,Sum = 24

因为,对于更高长度的子数组,乘积可以更大,以模1000000007计算。

对于所有可能长度的子数组,即 1、2、3、......、n,找到这些和的有效方法是什么,其中 n 是数组的长度.

【问题讨论】:

是针对所有子数组还是只针对长度为2的子数组? 对所有可能长度为 1、2、3、......、n 的子数组计算总和。 限制nk? @MetaD 真可惜,因为 2 真的很简单 :)(n 加法,n 减法和 n 乘法) n 和 k 可以达到 1000。 【参考方案1】:

有一个比较简单的方法: 构造术语(1 + A[i] * x)的乘积:

P = (1 + A[0] * x) * (1 + A[1] * x) * (1 + A[2] * x)...*(1 + A[n-1] * x)

如果我们打开括号,那么我们将得到多项式

P = 1 + B[1] * x + B[2] * x^2 + ... + B[n] * x^n

第 K 个系数 B[k] 等于长度为 K 的集合的乘积之和 - 例如,B[n] = A[0]*A[1]*A[2]*..A[n-1], B[2] = A[0]*A[1] + A[0]*A[2] + ... + A[n-2]*A[n-1] 等等。

所以要找到所有可能集合的乘积之和,我们必须找到 x = 1 的多项式 P 的值,然后减去 1 以删除前导第 0 项。如果我们不想考虑单元素集,则减去 B1 = A[i] 的总和。

例子:

(1+2)(1+3)(1+4) = 60
60 - 1 = 59
59 - (2 + 3 + 4) = 50 = 24 + 26 - as your example shows

【讨论】:

我没有正确阅读问题。我认为我们需要分别为每个 k 计算总和。这确实是正确答案。 如果我们想要的是所有非空子集上所有产品的总和,那么这应该是最有效的方法。如果我们想要部分和(即固定大小子集的部分),那么我看不出如何从中提取它们。【参考方案2】:

我们首先创建一个递归关系。令f(n, k) 为长度为n 的数组a 中长度为k 的子数组的所有乘积之和。基本情况很简单:

f(0, k) = 0 for all k
f(n, 0) = 1 for all n

第二条规则可能看起来有点违反直觉,但 1 是乘法的零元素。

现在我们找到了f(n+1, k) 的递归关系。我们想要所有大小为k 的子数组的乘积。这里有两种类型的子数组:包括a[n+1] 的子数组和不包括a[n+1] 的子数组。不包括a[n+1] 的总和正好是f(n, k)。包括a[n+1] 在内的所有子数组恰好都是长度为k-1 的子数组加上a[n+1],所以它们的和积是a[n+1] * f(n, k-1)

这完成了我们的递归关系:

f(n, k) = 0                               if n = 0
        = 1                               if k = 0
        = f(n-1, k) + a[n] * f(n-1, k-1)  otherwise

您可以使用一个巧妙的技巧来为您的动态编程使用非常有限的内存,因为函数 f 仅依赖于两个较早的值:

int[] compute(int[] a) 
    int N = a.length;
    int[] f = int[N];
    f[0] = 1;

    for (int n = 1; n < N; n++) 
        for (int k = n; k >= 1; k--) 
            f[k] = (f[k] + a[n] * f[k-1]) % 1000000007;
        
    

    return f;

【讨论】:

以上是关于所有长度为 k 的子数组的元素的乘积之和的主要内容,如果未能解决你的问题,请参考以下文章

最大子数组之和首位相邻32位版

最大子数组之和

数组643. 子数组最大平均数 I

刷题日记乘积小于K的子数组

刷题日记乘积小于K的子数组

刷题日记乘积小于K的子数组