斐波那契数列 x

(一)通项公式

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4
 5 using namespace std;
 6
 7 int main()
 8 {
 9     int n;
10     scanf("%d",&n);
11     n--;
12     double q=sqrt(5.0);
13     int ans;
14     ans=((pow((1+q)/2.0,n)/q-(pow((1-q)/2.0,n)/n)));
15     cout<<ans<<endl;
16     return 0;
17 }

(二)递归

  递归是最慢的,它会发生重复计算,时间复杂度成指数级。

1 long long f(int n)
2 {
3     if(n==0) return 0;
4   else if(n==1) return 1;
5   //else if(n==2) return 2;
6   else return f(n-1)+f(n-2);
7 }

但是通过记忆化搜索,能够将其复杂度降低为O(n)

代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #define M 100010
 4
 5 using namespace std;
 6
 7 bool v[M];//记忆化搜索
 8 long long f[M];//进行记录
 9
10 long long fb(int n)//递归
11 {
12     if(n==0) return 0;
13     if(n==1) return 1;//边界
14     if(v[n]) return f[n];//记忆化搜索
15     f[n]=fb(n-1)+fb(n-2);//进行记录
16     return f[n];
17 }
18
19 int main()
20 {
21     int n;
22     scanf("%d",&n);
23     cout<<fb(n);
24     return 0;
25 }

(三)循环

  利用临时变量来保存中间的计算过程,能够加快运算。

 1 long long f(int n)
 2 {
 3     long long a=1,b=2,c;
 4     if(n==1) return 1;
 5     if(n==2)return 2;
 6     else
 7     {
 8         for(int i=3; i<=n; i++)
 9         {
10             c=a+b;
11             a=b;
12             b=c;
13         }
14     }
15     return b;
16 }

(四)矩阵乘法+空间换时间(减少乘法,取模运算)

  数列的递推公式为:f(1)=1,f(2)=2,f(n)=f(n-1)+f(n-2)(n>=3)

   用矩阵表示为:

  进一步,可以得出直接推导公式:

  由于矩阵乘法满足结合律,在程序中可以事先给定矩阵的64,32,16,8,4,2,1次方,加快程序的执行时间。(有些题目需要取模运算,也可以事先进行一下)。给定的矩阵次幂,与二进制有关是因为,如下的公式存在解满足Xi={0或1}:

为了保证解满足 Xi={0或1},对上述公式的求解从右向左,即求解顺序为Xn,Xn-1,Xn-2,....,X1,X0。

  完整代码实现如下:

 1 /*求解f(n)%100000,其中n为大于等于3的正整数*/
 2
 3 #include<cstdio>
 4 #include<cmath>
 5
 6 long long f_tmp[6][4]=
 7 {  /*存放矩阵次幂*/
 8     /*位置:00 01 10 11*/
 9     {24578,78309,78309,46269},   //32次幂%100000
10     {1597,987,987,610},  //16次幂%100000
11     {34,21,21,13},   //8次幂%100000
12     {5,3,3,2},   //4次幂%100000
13     {2,1,1,1},   //2次幂%100000
14     {1,1,1,0},   //1次幂%100000
15 };
16
17 void f(int k)
18 { //k>=3
19     int i;
20     long long t00=1,t01=1,t10=1,t11=0;  //表示矩阵的1次幂
21     long long a,b,c,d;
22     k=k-3;  //公式中是n-2次幂,(t00,t01,t10,t11)表示1次幂。所以一共减3次
23     for(i=k; i>=32; i=i-32)
24     { //对于大于等于32的k;
25         a=(t00*f_tmp[0][0]+t01*f_tmp[0][2])%100000;
26         b=(t00*f_tmp[0][1]+t01*f_tmp[0][3])%100000;
27         c=(t10*f_tmp[0][0]+t11*f_tmp[0][2])%100000;
28         d=(t10*f_tmp[0][1]+t11*f_tmp[0][3])%100000;
29         t00=a;
30         t01=b;
31         t10=c;
32         t11=d;
33     }
34     i=4;
35     while(i>=0)
36     {  //对于小于32的k(16,8,4,2,1);
37         if(k>=(long long)pow(2,i))
38         { //如果k大于某一个2的次幂
39             a=(t00*f_tmp[5-i][0]+t01*f_tmp[5-i][2])%100000; ///(5-i):矩阵的2的i次幂在数组fac_tmp中的位置为fac_tmp[5-i]
40             b=(t00*f_tmp[5-i][1]+t01*f_tmp[5-i][3])%100000;
41             c=(t10*f_tmp[5-i][0]+t11*f_tmp[5-i][2])%100000;
42             d=(t10*f_tmp[5-i][1]+t11*f_tmp[5-i][3])%100000;
43             t00=a;
44             t01=b;
45             t10=c;
46             t11=d;
47             k=k-(int)pow(2,i);
48         }
49         i--;
50     }
51     a=(t00*2+t01*1)%100000;
52     printf("%lld\n",a);
53 }
54
55 int main()
56 {
57     int n;
58     scanf("%d",&n);
59     f(n);
60     return 0;
61 }

codevs题目直通:

http://codevs.cn/problem/1250/

代码如下:

 1 #include<iostream>
 2 #include<cstring>
 3
 4 using namespace std;
 5
 6 void multi(int a[2][2],int b[2][2],int q)//前缀
 7 {
 8     int c[2][2];
 9     memset(c,0,sizeof(c));//进行初始化清空,因为不只有一组数据,有t组
10     for(int i=0;i<2;i++)
11         for(int j=0;j<2;j++)
12             for(int k=0;k<2;k++)
13                 c[i][j]=(c[i][j]+(a[i][k]*b[k][j])%q)%q;
14     for(int i=0;i<2;i++)
15         for(int j=0;j<2;j++)
16             a[i][j]=c[i][j];
17 }
18
19 void fastpow(int n,int q)
20 {
21     int result[2][2]={1,0,1,0};
22     int a[2][2]={1,1,1,0};
23     while(n)//如果n不为0,一直做下面的循环
24     {
25         if(n&1)//表明如果它是奇数
26           multi(result,a,q);
27         multi(a,a,q);
28         n>>=1;//位运算,相当于n/2
29     }
30     int ans=result[0][1]%q;
31     cout<<ans<<endl;
32 }
33 int main ()
34 {
35     int t;//给出(t)多组数据
36     int n,q;//第几项,模几
37     cin>>t;
38     while(t--)
39     {
40         cin>>n>>q;
41         n++;//因为斐波那契数列是从第0项开始的
42         fastpow(n,q);//快速幂
43     }
44     return 0;
45 }

运用快速幂求解

洛谷题目直通

https://www.luogu.org/problem/show?pid=1962#sub

代码:   

#include<iostream>
#include<cstring>
#define Mod 1000000007LL
#define LL long long

using namespace std;

void multi(LL a[2][2],LL b[2][2])//前缀
{
    LL c[2][2];
    memset(c,0,sizeof(c));//进行初始化清空,因为不只有一组数据,有t组
    for(int i=0;i<2;i++)
        for(int j=0;j<2;j++)
            for(int k=0;k<2;k++)
                c[i][j]=(c[i][j]+(a[i][k]*b[k][j])%Mod)%Mod;
    for(int i=0;i<2;i++)
        for(int j=0;j<2;j++)
            a[i][j]=c[i][j];
}

void fastpow(LL n)
{
    LL result[2][2]={1,0,1,0};
    LL a[2][2]={1,1,1,0};
    while(n)//如果n不为0,一直做下面的循环
    {
        if(n&1)//表明如果它是奇数
          multi(result,a);
        multi(a,a);
        n>>=1;//位运算,相当于n/2
    }
    LL ans=result[0][1]%Mod;
    cout<<ans;
}
int main ()
{
    LL n;//第几项
    cin>>n;
    fastpow(n);
    return 0;
}

时间: 2024-10-24 21:02:20

斐波那契数列 x的相关文章

用递归和非递归的方法输出斐波那契数列的第n个元素(C语言实现)

费波那契数列(意大利语:Successione di Fibonacci),又译为费波拿契数.斐波那契数列.费氏数列.黄金分割数列. 在数学上,费波那契数列是以递归的方法来定义: {\displaystyle F_{0}=0} {\displaystyle F_{1}=1} {\displaystyle F_{n}=F_{n-1}+F_{n-2}}(n≧2) 用文字来说,就是费波那契数列由0和1开始,之后的费波那契系数就是由之前的两数相加而得出.首几个费波那契系数是: 0, 1, 1, 2, 3

Fibonacci斐波拉契数列----------动态规划DP

n==10 20 30 40 50 46 体验一下,感受一下,运行时间 #include <stdio.h>int fib(int n){ if (n<=1)     return 1; else            return fib(n-1)+fib(n-2); }int main( ){ int n; scanf("%d",&n); printf("%d\n" ,fib(n) );} 先 n==10 20 30 40 50 46

《剑指Offer》题目——斐波拉契数列

题目描述:大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项.(n<=39) 题目分析:如果使用简单的递归,很容易造成栈溢出.采用递推的方式即可. 代码: public class Fibonacci { public static int fibonacci(int n){ int res[] = new int[2]; res[0]=1; res[1]=1; int temp = 0; if(n==0) return 0; if(n<=2) return res[

js算法集合(二) javascript实现斐波那契数列 (兔子数列) Javascript实现杨辉三角

js算法集合(二)  斐波那契数列.杨辉三角 ★ 上一次我跟大家分享一下做水仙花数的算法的思路,并对其扩展到自幂数的算法,这次,我们来对斐波那契数列和杨辉三角进行研究,来加深对Javascript的理解. 一.Javascript实现斐波那契数列 ①要用Javascript实现斐波那契数列,我们首先要了解什么是斐波那契数列:斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为

斐波那契数列

前几天学了javascript,挺难的比之前学的H5难多了,之前还觉得H5很难,一比较之下就相形见绌了. 在JS里面代码什么的还是蛮简单的,就是逻辑问题让你绕不过来....在这些逻辑问题里又有一个既难而且十分经典的问题,那就是斐波那契数列. 斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为"兔子数列",指的是这样一个数列:1.1.2.3.5.8.13.21.34

斐波那契数列(分析别人的代码)

斐波那契数列指的是这样一个数列 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368........ 这个数列从第3项开始,每一项都等于前两项之和. n1 = 0 #给n1赋初始值 n2 = 1 #给n1赋初始值 count = 0 #给计数器初始值 while count < 10: #循环条件为计数器小于10 nth = n1 + n2 #n

快速求斐波那契数列(矩阵乘法+快速幂)

斐波那契数列 给你一个n:f(n)=f(n-1)+f(n-2) 请求出 f(f(n)),由于结果很大请 对答案 mod 10^9+7; 1<=n<=10^100; 用矩阵乘法+快速幂求斐波那契数列是经典应用: 矩阵公式 C i j=C i k *C k j; 根据递推式 构造2*2矩阵: 原始矩阵 1 0 0 1 矩阵 2 1 1 1 0 原始矩阵与矩阵 2相乘达到转化状态效果: 对矩阵二进行快速幂 乘法:达到快速转化矩阵的效果: 即使达到快速转化状态:那么大的数据范围也很难求解: 高精?这有

每日一九度之 题目1075:斐波那契数列

时间限制:5 秒 内存限制:32 兆 特殊判题:否 提交:3517 解决:2028 题目描述: 编写一个求斐波那契数列的递归函数,输入n值,使用该递归函数,输出如样例输出的斐波那契数列. 输入: 一个整型数n 输出: 题目可能有多组不同的测试数据,对于每组输入数据, 按题目的要求输出相应的斐波那契图形. 样例输入: 6 样例输出: 0 0 1 1 0 1 1 2 3 0 1 1 2 3 5 8 0 1 1 2 3 5 8 13 21 0 1 1 2 3 5 8 13 21 34 55 这题可以直

php实现斐波那契数列以及由此引起的联想

斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:0.1.1.2.3.5.8.13.21.34.……在数学上,斐波纳契数列以如下被以递归的方法定义:F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2)(n≥2,n∈N*)在现代物理.准晶体结构.化学等领域,斐波纳契数列都有直接的应用.————摘自百度百科 公式: F(n)=F(n

递归与斐波那契数列

一.递归 在函数内部,可以调用其他函数;如果一个函数在内部调用自己,那这个函数就是递归函数. 案例:遍历当前目录下的所有文件 1.递归遍历 1 import os 2 def gci(filepath): 3 #遍历filepath下所有文件,包括子目录 4 files = os.listdir(filepath) 5 for fi in files: 6 fi_d = os.path.join(filepath,fi) 7 if os.path.isdir(fi_d): 8 gci(fi_d)