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);
}
原文地址:https://www.cnblogs.com/wutongtong3117/p/7673602.html