如何找到第n个Fibonacci数的二进制表示

时间:2012-03-25 09:27:10

标签: binary fibonacci

这是我在这里的第一篇文章,所以如果我犯了一些错误,请告诉我。

我已经获得了一项任务,其中一部分需要第n个斐波纳契数的二进制表示。 约束 -

  1. )必须使用C ++作为编程。语言。
  2. )n'th fib。数字必须以lg(n)时间计算。
  3. 我有一个函数,但它适用于整数。但我必须计算的最大值约为10 ^ 6。所以,我被困在这里。 无论我知道什么,我都无法应用于这种情况,因为我可以产生第n个纤维。使用字符串,但会有线性时间复杂度。 以下是函数,

    void multiply(long int F[2][2], long int M[2][2]);
    void power(long int F[2][2], long int n);
    
    // Function to Calculate n'th fibonacci in log(n) time
    long int fib(long int n)
    {
        long int F[2][2] = {{1,1},{1,0}};
        if(n == 0)
            return 0;
        power(F, n-1);
        return F[0][0];
    }
    
    void power(long int F[2][2], long int n)
    {
        if( n == 0 || n == 1)
            return;
        long int M[2][2] = {{1,1},{1,0}};
    
        power(F, n/2);
        multiply(F, F);
    
        if( n%2 != 0 )
            multiply(F, M);
    }
    
    void multiply(long int F[2][2], long int M[2][2])
    {
        long int x =  (F[0][0]*M[0][0])%mod + (F[0][1]*M[1][0])%mod;
        long int y =  (F[0][0]*M[0][1])%mod + (F[0][1]*M[1][1])%mod;
        long int z =  (F[1][0]*M[0][0])%mod + (F[1][1]*M[1][0])%mod;
        long int w =  (F[1][0]*M[0][1])%mod + (F[1][1]*M[1][1])%mod;  
        F[0][0] = x;
        F[0][1] = y;
        F[1][0] = z;
        F[1][1] = w;
    }
    
    int main(){
        int n; cin >> n; cout << fib(n)<<endl; getchar();
    }
    

    可以看出,此功能中只能使用预定义的数据类型。

2 个答案:

答案 0 :(得分:0)

由于这是作业,我只会给你一些提示。

这两个问题是无关的,所以你需要两种方法:toBinary和fib。 toBinary (fib (n));将是您的解决方案。

为了解决toBinary部分,除法和模数很有用,可以递归调用。

如果计算fib(n)为fib(n-1)+ fib(n-2),则有一个陷阱进入,当你计算fib(n-1)为fib(n-2)时+ fib(n-3),你最终计算fib(n-2)两次,fib(n-3)三次,依此类推。

相反,你应该从(0 + 1)开始向上步,向前传递已经计算过的。


经过短暂的测试,我看到斐波那契数字的增长速度有多快。您是否可以访问任意大小的Int,或者您是否希望使用预分配的数组?

然后你需要一个add方法,它将较低和较高的数字作为整数或布尔数组,并在较低的数组中创建总和,然后变为上部数组。


更新

既然你已经解决了这个问题,我可以随意发布我的解决方案,以Scala编写:

import annotation._
/**
  add two arrays recursively. carry the position pos and the overrun 
   overrun=0   = 1      0      1      0      1
   Sum    low        | next        |  Sum
          0 1        | overrun     |  %2
  high 0| 0 1   1 2  | 0 0    0 1  | 0 1    1 0 
       1| 1 2   2 3  | 0 1    1 1  | 1 0    0 1
*/
@tailrec 
def add (low: Array[Int], high: Array[Int], pos: Int = 0, overrun: Int = 0): Array[Int] = {
  if (pos == higher.size) {
    if (overrun == 0) low else sys.error ("overrun!")
  } else {
    val sum = low (pos) + high (pos) + overrun
    low (pos) = (sum % 2)
    add (low, high, pos + 1, if (sum > 1) 1 else 0)
  }
}

/** call cnt (example: 5) steps of 
   fib (5, 0, 1), 
   fib (4, 1, 1), 
   fib (3, 1, 2), 
   fib (2, 2, 3), 
   fib (1, 3, 5), 
   fib (0, 5, 8) */
@tailrec 
def fib (cnt: Int, low: Array[Int], high: Array[Int]): Array[Int] = {
  if (cnt == 0) low else fib (cnt - 1, high, add (low, high)) }

/** generate 2 Arrays, size dependent on n of about 0.7*n + 1, big enough to
    hold values and result. Result has to be printed in reverse order, from the highest bit
*/
def fibonacci (n: Int) = {
  val lower =  Array.fill (n * 7 / 10 + 1)(0) // [...000]
  val higher = Array.fill (n * 7 / 10 + 1)(0) // [...000]
  higher (0) = 1 // [...001]
  val res = fib (n, lower, higher)
  res.reverse.foreach (print)
  println ()
  res
}

fibonacci (n)

对于斐波那契(10000),我得到了近7000个二进制数字的结果,并且关系10/7是常数,因此百万分之斐波纳契数字将具有大约1.4M的数字。

答案 1 :(得分:0)

更好的方法是使用Matrix Exponentiation,它将计算n'th fib。在lg(n)时间。 (适用于各种在线编码竞赛)参见This帖子的方法4。