矩阵快速幂简介

引入
思考一个问题:求斐波那契数列的第10^18对1e9+7取余的结果。
首先,如果按暴力递推的方法必定超时,那么现在就要引入一个新的算法了:矩阵快速幂,时间复杂度为log(n),这样就可以轻松的解决这个问题了。
算法前提
这里就不多介绍这两个算法的原理了,可课下自行查找
直接上代码:
1、整数快速幂。
快速求出a的k次方然后对p取余的结果

typedef long long ll;
int pmi(ll a,ll k,ll p){
    ll res=1;
    while(k){
    if(k&1) res=res*a%p;
    a=a*a%p;
    k>>=1;
    }
    return res;
}

2、矩阵乘法。
求矩阵A乘以矩阵B的结果(结果矩阵中的所有数都对mod取余)

Node mu(Node A,Node B,int mod) {
    Node ans;
    ans.init();
    for(int i=1; i<7; i++) {
        for(int j=1; j<7; j++) {
            for(int k=1; k<7; k++)
                ans.a[i][j]=(ans.a[i][j]%mod+A.a[i][k]%mod*B.a[k][j]%mod)%mod;
        }
    }
    return ans;
}

算法原理
斐波那契数列的地推式为:f[1]=f[2]=1 (n<=2) , f[n]=f[n-1]+f[n-2] (n>2);
那么这里只讨论n>2的情况就够了
不难发现 :
f[n+1]=f[n]+f[n-1]
f[n]=f[n-1]+f[n-2]
这连个矩阵是有联系的,这不是废话吗
现在可以设矩阵A是a[1][2] = { f[n-1], f[n-2] },矩阵B是b[2][2]={ {1, 1}, {1, 0} },这里就可以发现了:矩阵A乘以矩阵B就等于{ f[n], f[n-1] },那么这样就可以直接去第一个元素就是f[n]了。
我们可以继续从矩阵a[1][2] = { f[n-1], f[n-2] }往下推,不难发现:矩阵a[1][2]={ 1, 1 }乘以b[2][2]={ {1, 1}, {1, 0} }的n-2次方就等于矩阵{ f[n], f[n-1] }
这样就有了矩阵快速幂的算法。
那么问题来了:我们该如何构造矩阵A和B呢?
一般情况下 我们会得到一个递推式 例如f[n]=f[n-1]+f[n-2]+1,f[1]=f[2]=1;
因为f[n]=f[n-1]+f[n-2]+1,这样我们就要把A矩阵设为A={ f[2], f[1], 1},因为我们最终要到的矩阵为{ f[n], f[n-1], 1 },我们就要看他的前一项是多少,显然,他的前一项是{ f[n-1], f[n-2], 1 },我们要构建一个矩阵与{ f[n-1], f[n-2], 1 }可以得到{ f[n], f[n-1], 1 },显然这个矩阵大小是33的
通过思考我们不难发现这个B矩阵就是
0 1 0
1 1 0
0 1 1
所以就得到了A
B^(n-2)={ f[n], f[n-1], 1 };
这样的构造方法是要靠多练习的
今日份快乐传送门

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值