构造矩阵快速幂 又见斐波那契

本文介绍了一种利用矩阵快速幂解决斐波那契数列问题的方法,并通过具体的代码实现展示了如何构造矩阵来简化复杂的数学表达式,进而高效求解特定形式的递推序列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门:题目连接
思路:一看到n的数据范围和斐波那契,典型的矩阵快速幂,那么该这么构造呢?可见主要就是后面那个i^3 + i^2 + i^1 + 1这个地方有点难构造,其实不然,仔细算一下就会发现,i^3 = (i-1)^3 +3(i-1)^2 + 3(i-1) + 1 同理可以得到i^2 ,i 和1 所以构造函数就出来了,那么这题也就简单了。
这里写图片描述

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<stack>
#define eps 1e-7
#define INF 0x3f3f3f3f
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define say printf
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>PII;
const int mod = 1000000007;
struct Mat{
    ll a[6][6];   //会爆int的。
};
ll n;
Mat mul(Mat A, Mat B){
    Mat C;
    memset(C.a,0,sizeof(C.a));
    for(int i=0;i<6;i++){
        for(int k=0;k<6;k++){
            for(int j=0;j<6;j++){
                C.a[i][j] = (C.a[i][j]+A.a[i][k]*B.a[k][j])%mod;
            }
        }
    }
    return C;
}
Mat pow(Mat A,ll n){
    Mat B;
    memset(B.a,0,sizeof(B.a));
    for(int i=0;i<6;i++){
        B.a[i][i] = 1;
    }
    while(n>0){

        if(n&1) B = mul(B,A);
        A = mul(A,A);
        n >>= 1;
    }
    return B;
}
void solve(){
    Mat res;
    memset(res.a,0,sizeof(res.a));
    for(int i=0;i<6;i++) res.a[0][i] = 1;
    for(int i=1;i<6;i++) res.a[1][i] = 0;
    res.a[1][0] = 1;
    res.a[2][0] = 0;res.a[2][1] = 0;res.a[2][2] = 1;
    res.a[2][3] = 3;res.a[2][4] = 3;res.a[2][5] = 1;
    res.a[3][0] = 0;res.a[3][1] = 0;res.a[3][2] = 0;
    res.a[3][3] = 1;res.a[3][4] = 2;res.a[3][5] = 1;
    res.a[4][0] = 0;res.a[4][1] = 0;res.a[4][2] = 0;
    res.a[4][3] = 0;res.a[4][4] = 1;res.a[4][5] = 1;
    res.a[5][0] = 0;res.a[5][1] = 0;res.a[5][2] = 0;
    res.a[5][3] = 0;res.a[5][4] = 0;res.a[5][5] = 1;
    res = pow(res,n-1);
    int sum=(res.a[0][0]*1 + res.a[0][1]*0 + res.a[0][2]*8 + res.a[0][3]*4 + res.a[0][4]*2 + res.a[0][5])%mod;
    printf("%d\n",sum);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%lld",&n);
        solve();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值