zoukankan      html  css  js  c++  java
  • luogu1962斐波那契数列

    题目背景

    大家都知道,斐波那契数列是满足如下性质的一个数列:

    • f(1) = 1
    • f(2) = 1
    • f(n) = f(n-1) + f(n-2) (n ≥ 2 且 n 为整数)

    题目描述

    请你求出 f(n) mod 1000000007 的值。

    输入输出格式

    输入格式:
    ·第 1 行:一个整数 n

    输出格式:
    第 1 行: f(n) mod 1000000007 的值

    输入输出样例

    输入样例#1:
    5
    输出样例#1:
    5

    输入样例#2:
    10
    输出样例#2:
    55

    说明
    对于 60% 的数据: n ≤ 92
    对于 100% 的数据: n在long long(INT64)范围内。

    在这道题中,我们可以仔细的介绍一下矩阵乘法:
    一个m行n列的矩阵与一个n行p列的矩阵可以相乘,得到的结果是一个m行p列的矩阵,
    其中的第i行第j列位置上的数为第一个矩阵第i行上的n个数与第二个矩阵第j列上的n个数对应相乘后所得的n个乘积之和。
    矩阵乘法满足结合律,但不满足交换律和约去律
    矩阵加法就是相同位置的数字加一下。
    这里写图片描述
    矩阵减法也类似。
    矩阵乘以一个常数,就是所有位置都乘以这个数。
    这里写图片描述
    但是,等到矩阵乘以矩阵的时候,一切就不一样了。
    这里写图片描述
    这里写图片描述
    这要怎么理解呢
    矩阵的本质就是线性方程式,两者是一一对应关系。如果从线性方程式的角度,理解矩阵乘法就毫无难度。
    下面是一组线性方程式。
    这里写图片描述
    矩阵的最初目的,只是为线性方程组提供一个简写形式。
    这里写图片描述
    老实说,从上面这种写法,已经能看出矩阵乘法的规则了:系数矩阵第一行的2和1,各自与 x 和 y 的乘积之和,等于3。不过,这不算严格的证明,只是线性方程式转为矩阵的书写规则。
    下面才是严格的证明。有三组未知数 x、y 和 t,其中 x 和 y 的关系如下。
    这里写图片描述
    x 和 t 的关系如下。
    这里写图片描述
    有了这两组方程式,就可以求 y 和 t 的关系。从矩阵来看,很显然,只要把第二个矩阵代入第一个矩阵即可。
    这里写图片描述
    从方程式来看,也可以把第二个方程组代入第一个方程组。
    这里写图片描述
    上面的方程组可以整理成下面的形式。
    这里写图片描述
    最后那个矩阵等式,与前面的矩阵等式一对照,就会得到下面的关系。
    这里写图片描述
    矩阵乘法的计算规则,从而得到证明。

    好,那我们再看这道题
    矩阵如下:
    这里写图片描述
    那就会问了:是怎么求出来的呢?
    这里写图片描述
    这下就明白了吧~
    所以我们需要计算的就是:
    这里写图片描述

    这里写代码片
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #define LL long long
    
    using namespace std;
    
    const LL mod=1000000007;
    const int N=10;
    int n;
    struct node{
        int m[N][N];
        node operator * (const node &a) const{
            node c={};  //需要另用一个矩阵计算乘法的结果 
            for (int i=1;i<=n;i++)
                for (int j=1;j<=n;j++)
                    for (int k=1;k<=n;k++)
                        c.m[i][j]=(c.m[i][j]+(LL)m[i][k]*a.m[k][j])%mod;
            return c;
        }
        void clear()
        {
            memset(m,0,sizeof(m));
        }
        node KSM(LL p)  //快速幂模板 
        {
            node an=(* this),a=(*this); 
    //      an.clear();
    //      for (int i=1;i<=n;i++)
    //          an.m[i][i]=1;
            while (p)
            {
                if (p&1)
                   an=an*a;
                a=a*a;
                p>>=1;
            }
            return an;
        }
    };
    
    main()
    {
        LL p;
        scanf("%lld",&p);
        node m,ans;
        m.m[1][1]=1; m.m[1][2]=1;
        m.m[2][1]=1; m.m[2][2]=0;
        n=2;
        ans=m.KSM(p-1);
        printf("%d
    ",(ans.m[2][1])%mod);
    }
  • 相关阅读:
    css滚动条设置
    动态背景插件three.min.ts
    富文本编辑器ckeditor使用(angular中)
    angular接口传参
    angular组件图标无法显示的问题
    angular项目搭建
    使用Flume
    centos7 安装Flume
    centos7 安装kubernetes
    Nginx的rewrite对地址进行重写
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673602.html
Copyright © 2011-2022 走看看