矩阵优化递推数列

Problem

求斐波那契数列第n项,输出答案模10^9+7的值(n<2^63)

Prepare

(对于学过线代的大佬请跳至Solution)

我们先介绍一下矩阵,我们表现形式就是二维数组。而矩阵相对于二维数组不同的是具有乘法运算。

对于n*m的矩阵a和m*p的矩阵b,表示a*b的矩阵c是n*p的,其中矩阵c的第i行j列的元素满足


举个栗子,如下:


顺便指一下,对于n*n的矩阵,唯一存在这个矩阵a,使得对于任意矩阵b,a*b=b,其中a的主对角线上所有数为1,其他数为0

如果还是看不懂,百度百科

Solution

对于斐波那契数列f(n)满足f(n)=f(n-1)+f(n-2)(废话!)

我们构造矩阵a,使得:


所以,我们可以通过计算a^n来得到答案,诶,这不是也要O(n)时间吗?别忘了还有快速幂(kasumi),和普通整数的求幂大抵相差不了多少。

Code

#include<cstdio>
#include<cstring>
#define MOD 1000000007
using namespace std;
typedef long long LL;
struct Matrix {
    int n;
    LL a[2][2];
    Matrix():n(2){memset(a,0,sizeof(a));}
    Matrix operator*(const Matrix& mat){
        Matrix res;
        for(int i=0;i<n;i++)
            for(int j=0;j<mat.n;j++)
                for(int k=0;k<n;k++)
                    res.a[i][j]=(a[i][k]*mat.a[k][j]%MOD+res.a[i][j])%MOD;
        return res;
    }
    Matrix operator=(const Matrix& mat){memcpy(a,mat.a,sizeof(a));}
};
Matrix kasumi(Matrix d,LL k){
    Matrix ans;
    for(int i=0;i<ans.n;i++) ans.a[i][i]=1;
    while(k){
        if(k&1) ans=ans*d;
        d=d*d;
        k>>=1;
    }
    return ans;
}
int main(){
    Matrix d;
    LL n;
    scanf("%lld",&n);
    d.a[0][0]=d.a[0][1]=d.a[1][0]=1;
    printf("%lld",kasumi(d,n).a[1][0]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值