Fibonacci数的乘积和

时间:2012-09-03 13:11:54

标签: c++ algorithm math fibonacci

给出一系列

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。

我希望将此系列缩减为单个术语或其他一些优化以提高 * 时间复杂度。 *

有什么建议吗?

4 个答案:

答案 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>2f(1)=f(2)=1f(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))/5L(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所示。