来提供两个正确的做法:

  • 斐波那契数列双倍项的做法(附加证明)
  • 矩阵快速幂

一、双倍项做法

在偶然之中,在百度中翻到了有关于斐波那契数列的词条(传送门),那么我们可以发现一个这个规律$ \frac{F_{2n}}{F_{n}}=F_{n-1}+F_{n+1} $,那么我就想到了是不是可以用这个公式实现类似于快速幂之类的东西:power(n,m)=power(n*n,m/2) m mod 2=0 power(n,m)=power(n*n,m/2)*n m mod 2=1

快速幂这个东西,是分成偶数情况和奇数情况,所以我们只是知道偶数想的计算公式,所以我们接下来要推导一下奇数项的递归式
\[ F_{2n}=F_{n}\times(F_{n-1}+F_{n+1})\]
\[ F_{2n+2}=F_{n+1}\times(F_{n}+F_{n+2})\]
那么我们就是要从\(F_{2n}\)和\(F_{2n+2}\)推导求出\(F_{2n+1}\)
\[ F_{2n+1}=F_{2n+2}-F_{2n} \]
\[ F_{2n+1}=F_{n+1}\times(F_{n}+F_{n+2})-F_{n}*(F_{n-1}+F_{n+1}) \]
\[ F_{2n+1}=F_{n+1}\times F_{n}+F_{n+1}\times F_{n+2} - F_{n}\times F_{n-1}-F_{n}\times F_{n+1}\]
\[ F_{2n+1}=F_{n+1}\times F_{n+2}-F_{n}\times F_{n-1}\]
\[ F_{2n+1}=F_{n+1}\times(F_{n+1}+F_{n})-F_{n}\times(F_{n+1}-F_{n})\]
\[ F_{2n+1}={F_{n+1}}^2+{F_{n}}^2 \]
以上就是我们对于这个公式的推导
那么我们就得到了

F[2n] = F[n+1]² - F[n-1]² = (2F[n-1] + F[n]) · F[n]

F[2n+1] = F[n+1]² + F[n]²

那么,我们在写一个map,那么就可以不用全部都递归到底了,优化一下。
用map映射一下大数,映射到我们的答案上。

#include <bits/stdc++.h>
using namespace std;
const int Mod=1e9+7;//mod数
long long n;
map<long long,long long> ma;//搞映射
inline long long work(long long x){
    if(x==1||x==0)return 1;//边界
    if(ma.count(x))return ma[x];//count如果是返回1那么就是这个答案已经在map中映射过了,0就是没有
    long long res=0,t=x/2;
    if(x&1) res=work(t)*(work(t-1)+work(t+1))%Mod;//公式2
    else res=work(t)*work(t)%Mod+work(t-1)*work(t-1)%Mod;//公式1
    return ma[x]=res;
}
int main() {//主程序
    cin>>n;
    long long res=work(n-1)%Mod;
    cout<<res<<endl;
    return 0;
}

注:这个程序的复杂度是也差不多是log(n),也是非常优的解法


二、矩阵乘法解法

这个解法应该是这一道题的正解。

我是一个蒟蒻,还是只是初懂矩阵乘法的小白。

我就贴一下自己的代码,详细的题解还是看一下别的大佬的题解。

#include <bits/stdc++.h>
using namespace std;
#define mod 1000000007 //Mod数
struct Matrix{//这个是矩阵的结构体
    long long ma[2][2];
};
Matrix mul(Matrix A,Matrix B)//矩阵乘法
{
    Matrix C;//答案矩阵
    C.ma[0][0]=C.ma[0][1]=C.ma[1][0]=C.ma[1][1]=0;//初始化
    for(int i=0;i<2;i++)
    {
        for(int j=0;j<2;j++)
        {
            for(int k=0;k<2;k++)
            {
                C.ma[i][j]=(C.ma[i][j]+A.ma[i][k]*B.ma[k][j])%mod;
            }
        }
    }
    return C;
}
Matrix pow_mod(Matrix A,long long n)//卡苏米+矩阵乘法优化
{
    Matrix B;
    B.ma[0][0]=B.ma[1][1]=1;
    B.ma[0][1]=B.ma[1][0]=0;
    while(n) {
        if(n&1) B=mul(B,A);
        A=mul(A,A);
        n>>=1;
    }
    return B;
}
int main()
{
    long long n;
    Matrix A;
    A.ma[0][0]=1;A.ma[0][1]=1;
    A.ma[1][0]=1;A.ma[1][1]=0;//初始的数组
    Matrix ans=pow_mod(A,n);
    printf("%lld\n",ans.ma[0][1]);//输出答案
    return 0;
}

[luogu1962]斐波那契数列的更多相关文章

  1. C#求斐波那契数列第30项的值(递归和非递归)

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  2. 斐波拉契数列加强版——时间复杂度O(1),空间复杂度O(1)

    对于斐波拉契经典问题,我们都非常熟悉,通过递推公式F(n) = F(n - ) + F(n - ),我们可以在线性时间内求出第n项F(n),现在考虑斐波拉契的加强版,我们要求的项数n的范围为int范围 ...

  3. js中的斐波那契数列法

    //斐波那契数列:1,2,3,5,8,13…… //从第3个起的第n个等于前两个之和 //解法1: var n1 = 1,n2 = 2; for(var i=3;i<101;i++){ var ...

  4. 剑指Offer面试题:8.斐波那契数列

    一.题目:斐波那契数列 题目:写一个函数,输入n,求斐波那契(Fibonacci)数列的第n项.斐波那契数列的定义如下: 二.效率很低的解法 很多C/C++/C#/Java语言教科书在讲述递归函数的时 ...

  5. 算法: 斐波那契数列C/C++实现

    斐波那契数列: 1,1,2,3,5,8,13,21,34,....     //求斐波那契数列第n项的值 //1,1,2,3,5,8,13,21,34... //1.递归: //缺点:当n过大时,递归 ...

  6. 洛谷P1962 斐波那契数列 || P1349 广义斐波那契数列[矩阵乘法]

    P1962 斐波那契数列 大家都知道,斐波那契数列是满足如下性质的一个数列: • f(1) = 1 • f(2) = 1 • f(n) = f(n-1) + f(n-2) (n ≥ 2 且 n 为整数 ...

  7. Python递归及斐波那契数列

    递归函数 在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数.举个例子,我们来计算阶乘 n! = 1 * 2 * 3 * ... * n,用函数 fact(n)表示,可 ...

  8. 简单Java算法程序实现!斐波那契数列函数~

    java编程基础--斐波那契数列 问题描述:一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法. 思路:可能出现的情况:(1) n=1 ,一种方法 ;(2)n=2 ...

  9. js 斐波那契数列(兔子问题)

    对于JS初学者来说,斐波那契数列一直是个头疼的问题,总是理不清思路. 希望看完这篇文章之后会对你有帮助. 什么是斐波那契数列 : 答: 斐波那契数列,又称黄金分割数列.因数学家列昂纳多·斐波那契(Le ...

随机推荐

  1. Linux下查找进程id并强制停止进程的脚本

    Linux下的tomcat的停止脚本shutdown.sh经常失败,造成tomcat进程没关闭.所以只能手动查找进程id,然后用kill命令来强制停止.每次都要这样查一下,然后再杀进程.感觉有点麻烦, ...

  2. C#基础巩固(3)-Linq To XML 读取XML

    记录下一些读取XML的方法,以免到用的时候忘记了,还得花时间去找. 一.传统写法读取XML 现在我有一个XML文件如下: 现在我要查找名字为"王五"的这个人的 Id 和sex(性别 ...

  3. 【JVM.12】线程安全与锁优化

    一.概述 面向过程的编程思想极大地提升了现代软件开发的生产效率和软件可以达到的规模,但是现实世界与计算机世界之间不可避免地存在一些差异,本节就如何保证并发的正确性和如何实现线程安全讲起. 二.线程安全 ...

  4. 正则&highlight高亮实现(干货)

    写完正则表达式以后在浏览器上检测实在是不方便,于是就写了一个JS正则小工具,大大地提高了学习效率.学习之余用正则实现了一个highlight高亮demo,欢迎交流. 什么是正则表达式? 简单的说:正则 ...

  5. 《Linux内核设计与实现》读书笔记 3

    第三章 进程管理 3.1进程 概念: 进程:处于执行期的程序.但不仅局限于程序,还包含其他资源(打开的文件,挂起的信号,内核内部数据,处理器状态,一个或多个具有内催音社的内存地址空间及一个或多个执行线 ...

  6. Can't find model 'en'

    在使用 nlp = spacy.load("en") 报错OSError: Can't find model 'en' 应该用 python -m spacy download e ...

  7. CSS编码规则

    /* 和HTML一样使用两个空格来代替制表符 */ div { /* 为了代码的易读性,在每个声明块的左花括号前添加一个空格 */' padding: 15px; /* 每个声明语句的:后应该插入一个 ...

  8. 毕设之c#多线程学习(官方+转载)

    官方文档,原址:打开 如何:对 Windows 窗体控件进行线程安全调用   使用多线程提高 Windows 窗体应用程序的性能时,必须注意以线程安全方式调用控件. 示例 访问 Windows 窗体控 ...

  9. 定义类型别名(typedef,using)

    说到类型别名,无非是给类型名(如int,char,float,double,bool)取一个比较有特殊含义的名字而已 最常用的关键莫过于 typedef 吧 typedef最常见的用法是与结构体str ...

  10. PAT 1049 数列的片段和

    https://pintia.cn/problem-sets/994805260223102976/problems/994805275792359424 给定一个正数数列,我们可以从中截取任意的连续 ...