又见斐波那契 (矩阵)

知识储备:矩阵的应用以及快速幂

原题2018年湘潭大学程序设计竞赛 G

题意

这里写图片描述


解析

老套路,首先用列向量的形式写出项矩阵:

        | f(i-1) |                  |  f(i)  | 
        | f(i-2) |                  | f(i-1) | 
        |  i^3   |     ->           | (i+1)^3|    
A[i-1]  |  i^2   |     ->    A[i]   | (i+1)^2|
        |   i    |                  |   i+1  |
        |   1    |                  |    1   |

一行一行推出乘积矩阵:

    | 1 1 1 1 1 1 |
    | 1 0 0 0 0 0 |
    | 0 0 1 3 3 1 |
B   | 0 0 0 1 2 1 |
    | 0 0 0 0 1 1 |
    | 0 0 0 0 0 1 |

也就是B*A[i-1]=A[i]

最后注意一下T和n都要用long long


代码


#include<stdio.h>
#include<string.h>
#define D long long
#define N 8
const D MOD =((D)1e9+7);
struct matrix{
    int size;
    D mat[N][N];
    matrix(int s){
        size=s;memset(mat,0,sizeof(mat));
    }
    matrix operator * (const matrix & x)const{
        matrix ans(x.size);
        for(int i=1;i<=x.size;i++){
            for(int j=1;j<=x.size;j++){
                for(int k=1;k<=x.size;k++){
                    ans.mat[i][j]=(ans.mat[i][j]+mat[i][k]*x.mat[k][j])%MOD;
                }
            }
        }return ans;
    }
} ;
matrix ans(6);
void swift(matrix a,D t){
    for(int i=1;i<=a.size;i++)ans.mat[i][i]=1;
    while(t){
        if(t&1)ans=ans*a;
        a=a*a;t>>=1;
    }
}
matrix f1(6);
int main(){
    f1.mat[1][1]=1,f1.mat[2][1]=0,f1.mat[3][1]=8,f1.mat[4][1]=4,f1.mat[5][1]=2,f1.mat[6][1]=1;
    matrix bas(6);
    D tmp[7][7]={
        {0,0,0,0,0,0,0},
        {0,1,1,1,1,1,1},
        {0,1,0,0,0,0,0},
        {0,0,0,1,3,3,1},
        {0,0,0,0,1,2,1},
        {0,0,0,0,0,1,1},
        {0,0,0,0,0,0,1}
    };
    for(int i=1;i<=6;i++){
        for(int j=1;j<=6;j++){
            bas.mat[i][j]=tmp[i][j];
        }
    }
    D t;scanf("%lld",&t);while(t--){
        D n;scanf("%lld",&n);
        if(n<2)printf("%lld\n",n);
        else{
            swift(bas,n-1);ans=ans*f1;
            printf("%lld\n",ans.mat[1][1]);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值