我有一个N
个数字的数组A.我必须找到所有子阵列之和的斐波纳契数的总和。
例如:
A = {1,1}
F[Sum A[1,1]] = F[1] = 1
F[Sum A[1,2]] = F[2] = 1
F[Sum A[2,2]] = F[1] = 1
Ans = 1 + 1 + 1 = 3
问题类似于this,但我需要计算标准Fibonacci序列的总和。
这是source code。
这里使用了什么属性?
任何人都能解释这背后的数学吗?如何避免O(N^2)
解决方案?如何修改标准Fibonacci数的源代码?
答案 0 :(得分:0)
这是一个在O(N * log MAX_A * k^3)
时间内运行的解决方案(其中MAX_A
是数组中的最大值,k
是递归公式中使用的变量数(等于2对于斐波纳契和3对于你的问题链接的问题。)我不会参考你提供的源代码,因为它很难阅读,但看起来它使用类似的想法:
让我们快速了解如何计算i-th
斐波纳契数。很容易看出f(i) = F^n * [1, 1].transposed()
,其中F
是一个矩阵[[1, 1], [1, 0]]
(对于原始问题,它将是[[1, 1, 1], [1, 0, 0], [0, 0, 1]]
。我们可以找到{{1}使用二进制求幂快速矩阵的幂。
让我们进一步发展这个想法。就矩阵而言,我们要求评估以下表达式:
n-th
或等效地(因为矩阵乘法对于加法是分布式的)
sum for all valid L, R of ((F^(a[L] + ... + a[R]) * [1, 1].transposed())[0])
现在我们需要弄清楚如何有效地计算这个总和。让我们学会逐步进行。让我们假设已经处理了位于((sum for all valid L, R of F^(a[L] + ... + a[R])) * [1, 1].transposed())[0]
或更小位置的所有子数组,并且我们想要添加下一个。根据问题陈述,我们应该在答案中添加n
,这等于F^a[n + 1] + F^(a[n + 1] + a[n]) + ... + F^(a[n + 1] + a[n] + ... + a[0])
。
那就是它。我们已经有了有效的解决方案。这里有一个伪代码:
F^a[n + 1] * (F^a[n] + F^(a[n] + a[n - 1]) + ... + F^(a[n] + a[n - 1] + ... + a[0]))
假设矩阵pref_sum = I // identity matrix. This variable holds the second
// term of the product used in step 3
total_sum = zeros // zero matrix of an appropriate size
// It holds the answer to the problem
for i = 0 .. N - 1
cur_matrix = binary_exponentiation(F, a[i]) // A matrix for the a[i]-th fibonacci number
// Everything is updated according to the formulas shown above
total_sum += pref_sum * cur_matrix
pref_sum = pref_sum * cur_matrix + I
// Now we just need to mulitiply the total_sum by an appropriate vector
// which is [1, 1].transposed() in case of Fibonacci numbers
的大小是常数(在Fibonacci数的情况下再次为2),时间复杂度为F
,因为只有对原始数组的每个元素进行一次二进制求幂,然后进行恒定数量的矩阵乘法和加法。