给出一系列
Fib(1)* Fib(n + 2)+ Fib(2)* Fib(n + 1)+ Fib(3)* Fib(n)+ ...... + Fib(n-1) * Fib(4)
或求和 Fib(x)* Fib(n-x + 3)其中x从1变化到n-1 其中Fib(n)是第n个Fibonacci系列
评估该系列Fib(n)可以使用矩阵求幂来计算。
但是这个的复杂性是logn,对于n个术语,它将是nlogn。
我希望将此系列缩减为单个术语或其他一些优化以提高 * 时间复杂度。 *
有什么建议吗?
答案 0 :(得分:3)
我无法将总和减少到单个术语,但可以将其减少为五个术语的总和,从而降低了O(log n)
算术运算的复杂性。
但是,Fib(n)
具有Θ(n)
位,因此位操作的数量不是对数的。 Fib(n)
的大小与n-1
相乘,因此位操作的数量为M(n,log n)
,其中M(a,b)
是a的位操作复杂度将a
- 位数与b
- 位数相乘。对于朴素算法M(a,b) = a*b
,以下算法中的位操作数为O(n*log n)
。
允许这种减少的事实是Fibonacci数(就像由线性递归定义的序列中的所有数字)可以写成纯指数项的总和,特别是
Fib(n) = (α^n - β^n) / (α - β)
,其中
α = (1 + √5)/2; β = (1 - √5)/2.
除斐波那契数字外,我还使用卢卡斯数,它与斐波那契数相同,
Luc(n) = α^n + β^n
所以卢卡斯数的序列(从索引0开始)以
开头2 1 3 4 7 11 18 29 47 ...
关系Luc(n) = Fib(n+1) + Fib(n-1)
允许在Fibonacci和Lucas数字之间轻松转换,Luc(n)
步骤中O(log n)
的计算可以重复使用Fibonacci代码。
因此,通过上面给出的Fibonacci数的表示,我们找到了
(α - β)^2 * Fib(k) * Fib(n+3-k) = (α^k - β^k) * (α^(n+3-k) - β^(n+3-k))
= α^(n+3) + β^(n+3) - (α^k * β^(n+3-k)) - (α^(n+3-k) * β^k)
= Luc(n+3) - ((-1)^k * α^(2k) * β^(n+3)) - ((-1)^k * α^(n+3) * β^(2k))
使用关系α * β = -1
。
现在,由于α - β = √5
总和k = 1, ..., n-1
产生了
n-1 n-1 n-1
5 * ∑ Fib(k)*Fib(n+3-k) = (n-1)*Luc(n+3) - β^(n+3) * ∑ (-α²)^k - α^(n+3) * ∑ (-β²)^k
k=1 k=1 k=1
几何总和可以用封闭的形式写出来,并且有点杂耍会产生公式
n-1
∑ Fib(k)*Fib(n+3-k) = [5*(n-1)*Luc(n+3) + Luc(n+2) + 2*Luc(n+1) - 2*Luc(n-3) + Luc(n-4)]/25
k=1
答案 1 :(得分:2)
要遵循的步骤:
定义std::vector<int>
并填写所需的所有斐波那契数字。使用dynamic programming计算这些数字;也就是说,利用已经计算过的结果。不要多次计算相同的值!
如果向量中填充了所需的所有数字,请在循环中应用公式Fib(x) * Fib (n-x+3)
并计算产品的总和。
答案 2 :(得分:2)
假设f(n)=f(n-1)+f(n-2)
和n>2
为f(1)=f(2)=1
,f(0)=0
允许E(n)=sum(k=1 .. n-1, f(k)f(n-k+3))
和E'(n)=sum(k=0 .. n, f(k)f(n-k))
显然E(n)=E'(n+3) - ( f(0)f(n+3) + f(n)f(3) + f(n+1)f(2) + f(n+2)f(1) + f(n+3)f(0) )
在wolfram上,您会找到:E'(n)= (nL(n)-f(n))/5
,L(n)=f(n+1)+f(n-1)
由此:
5E(n)=(n+3)( f(n+4)+f(n+2) ) - 5(2f(n) + f(n+1) +f(n+2))
5E(n)=(n+3)( 4f(n+1)+3f(n) ) - 10f(n+1) -15f(n)
5E(n)= (4n+2)f(n+1) + (3n-6)f(n)
应该很容易评估,复杂性应该与使用的fibonnaci算法相同,
答案 3 :(得分:1)
如果我知道Lucas number是什么,那么我可以使用身份......
F(n)* F(m)= [L(m + n) - ( - 1)^ n * L(m-n)] / 5
这样可以将斐波纳契数的乘积之和减少为卢卡斯数的总和。
更好的是,由于n + m对于每个项都是常数,因此总和进一步减少。此总和中有n-1个项,因此总和减少为Lucas数的总和。
[(n-1)* L(n + 3)+ L(n + 1) - L(n-1)+ L(n-3) - ...... +( - 1)^(n- 1)* L(5-N)] / 5
作为测试,对于n = 5,我得到40,这与产品的直接总和一致:
1 * 13 + 1 * 8 + 2 * 5 + 3 * 3 = 40
对于n = 1000,我得到一个总和:
82283375600539014079871356568026158421560221654785733943009487102720 211767741849325389562067921531531130739623611293922046989610820831567088 516047002196966545744637588824274730947688693969572937880383134671205375
更好的是,一些额外的工作将使卢卡斯数的总和进一步收缩,因为负数指数的卢卡斯数与具有正指数的数相关。
就计算第k个卢卡斯(以及第k个斐波那契)数而言,它可以非常有效地完成,如here所示。