LuoguP1962 斐波那契数列 解题报告【矩阵快速幂】

题目背景
大家都知道,斐波那契数列是满足如下性质的一个数列:
• 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)范围内。
解题报告
我们一看数据范围,n在long long范围内,看来就只能用矩阵快速幂了。
怎么用矩阵快速幂呢?
我们知道, f[n]=f[n1]1+f[n2]1 f]n1]=f[n1]1+f[n2]0 。那么根据矩阵乘法的性质,就有:


(转自这篇博客
又因为 f[1]=f[2]=1 ,所以我们不需要在意那个1*2的矩阵,直接算矩阵的^(n-1)就好了。
代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=2,mod=1e9+7;
struct mat
{
    ll c[N+5][N+5];
};
ll n;
mat mat_mul(mat a,mat b)
{
    mat ret;
    memset(ret.c,0,sizeof(ret.c));
    for(int i=1;i<=N;i++)
    for(int j=1;j<=N;j++)
    for(int k=1;k<=N;k++)
    ret.c[i][j]=(ret.c[i][j]%mod+a.c[i][k]*b.c[k][j]%mod)%mod;
    return ret;
}
ll mat_pow()
{
    mat base,ret;
    n-=2;
    memset(base.c,0,sizeof(base.c));
    memset(ret.c,0,sizeof(ret.c));
    base.c[1][2]=1,base.c[2][1]=1,base.c[1][1]=1;
    base.c[2][2]=0;
    ret.c[1][2]=1,ret.c[2][1]=1,ret.c[1][1]=1;
    ret.c[2][2]=0;
    for(ret;n;n>>=1,base=mat_mul(base,base))if(n&1)ret=mat_mul(ret,base);
    return ret.c[1][1];
}
int main()
{
    scanf("%lld",&n);
    if(n==0){printf("0");return 0;}
    if(n==1||n==2){printf("1");return 0;}
    printf("%lld\n",mat_pow());
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值