天天看点

大斐波那契数

斐波那契数计算公式  :

f(n)=f(n-1)+f(n-2)        (n>=3)

f(1)=1

f(2)=1

对于 n 比较小的情况下,下边的程序就可以实现这个功能

#include<cstdio>
#define ll long long 
const int n=100;
int main() 
{
  ll a[n];
  a[2]=1;a[1]=1;
  for(int i=3;i<n;i++)
    a[i]=a[i-1]+a[i-2];
  for(int i=1;i<n;i++)
    printf("%d   %lld\n",i,a[i]);
  return 0;
}      

结果如下:

大斐波那契数

请注意,当 n = 92的时候,结果还是正确的,但是 n 一旦超过92.long long 类型就无法储存这么大的数了

大斐波那契数

溢出了,所以我们需要寻找新的方法来计算 n 比较大的时候那些情况的斐波那契数

我们需要用到模拟的思想,开一个比较大的二维数组来储存每一个斐波那契数,再让它们的每一位相加最后得出的结果就是答案了,详情请看代码,

/*
  大斐波那契数 

*/
#include<cstdio>
#include<cstring>
#define ll long long
const int MAXN=1e4+3;
const int c=10000;
ll a[MAXN][MAXN];
int main()
{
  int n;
  while(~scanf("%d",&n))
  {
    a[1][0]=1;a[2][0]=1;//初始化 第一个数和第二个数 
    int dight=0;//斐波那契数的 位数 
    int temp=0;//储存进位
    for(int i=3;i<=n;i++)  //从3算到N
    {
      temp=0;//进位每次计算都要初始化为0
      for(int j=0;j<=dight;j++)
      {
        a[i][j]=a[i-1][j]+a[i-2][j]+temp;
        temp=a[i][j]/10;
        a[i][j]%=10;
       } 
      if(temp)//如果有进位的话 
      {
        dight++;//位数加一 
        a[i][dight]=temp;//给最高位赋值 
      }
     } 
    for(int i=dight;i>=0;i--)//逆序输出这个数组 
      printf("%lld",a[n][i]);//n代表是第n个斐波那契数,i是这个数的第i位 
    printf("\n");      
  }
  return 0;
}      

应该可以把这个代码优化一下,以便于计算更大的数

/*
  大斐波那契数 

*/

//这段代码让每一个a[i][j]的值都是9位 
#include<cstdio>
#include<cstring>
#define ll long long
const int MAXN=1e4+3;
const int c=1e9;
ll a[MAXN][MAXN];
int main()
{
  int n;
  while(~scanf("%d",&n))
  {
    a[1][0]=1;a[2][0]=1;
    int temp=0;
    int d=0;
    for(int i=3;i<=n;i++)
    {
      temp=0;
      for(int j=0;j<=d;j++)
      {
        a[i][j]=a[i-1][j]+a[i-2][j]+temp;
        temp=a[i][j]/c;
        a[i][j]%=c;
      }
      if(temp)
      {
        d++;
        a[i][d]=temp;
      }  
    }  
    printf("%lld",a[n][d]);
    for(int i=d-1;i>=0;i--)
      printf("%010lld",a[n][i]);
    printf("\n");
  }
  return 0;
}      

可以来这里联系一下:​​HDU_1715​​

AC代码如下:

#include<cstdio>
#include<cstring>
const int MAXN=1004;
int a[MAXN][MAXN];
int main()
{
  int t,n;
  scanf("%d",&t);
  while(t--)
  {
    scanf("%d",&n);
    a[1][0]=1,a[2][0]=1;
    int d=0;
    int temp=0;
    for(int i=3;i<=n;i++)
    {
      temp=0;
      for(int j=0;j<=d;j++)
      {
        a[i][j]=a[i-1][j]+a[i-2][j]+temp;
        temp=a[i][j]/10;
        a[i][j]%=10;
      }
      if(temp)
      {
        d++;
        a[i][d]=temp;
      }
    }
    for(int i=d;i>=0;i--)
      printf("%d",a[n][i]);
    printf("\n");
  }
  return 0;
}      

大斐波那契数和大数阶乘的思想是一样的,不同的是大数阶乘只用了一维数组,比这个要简单一些

import java.math.*;
import java.util.*;
public class Main{
  public static void main(String[] args){
    Scanner cin = new Scanner(System.in);
    BigInteger[] a;
    a = new BigInteger[2000];
    a[0] = BigInteger.ZERO;
    a[1] = BigInteger.ONE;
    for(int i=2;i<1005;i++)
      a[i] = a[i-1].add(a[i-2]);
    int  n = cin.nextInt();
    while(n-->0){
      int i = cin.nextInt();
      System.out.println(a[i]);
    }
  }
}