博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
快速幂矩阵小结
阅读量:5858 次
发布时间:2019-06-19

本文共 3920 字,大约阅读时间需要 13 分钟。

【目录】

1.快速幂(取模)

2.矩阵快速幂

 

一、快速幂(取模)

1.快速幂取模算法

const int  mod  = 1e9+7;long long qPow(long long a ,long long n){    long long ans = 1;    //如果n的二进制最后一位是1 结果参与运算     //因为如果是0,那么幂运算之后该项是1,1乘任何数还是那个数,对结果不影响    while(n > 0){        if(n & 1)              ans = (ans* a) % mod;        a = (a*a) % mod;//底数加倍         n >>= 1;//移位     }    return ans;    }

 

 

二、快速幂矩阵

1.适用场景

 a.清楚状态转移但无法求出通项公式或者递推公式。

 

(1)初始状态可设为单位阵

(2)通过简单试验可以得到状态转移矩阵

(3)后继状态可以通过当前状态转移之,其实就是在当前矩阵基础上乘上一个转移矩阵

(4)最终终态就是转移矩阵的n-k次方(k根据初态到终态需要转移多少次确定),考虑所有非零项之和或者是特定位置的数值

 

b.已知递推公式求第N项但是数值范围过大

用数组递推不仅会会超空间(比如109),而且会超时(朴素的一步一步递推速度太慢规模一大必然超时)

此时用类似于快速幂的思想加速转移,可以类比求21000时速度是越来越快的,求矩阵A的K次方速度也是越来越快的。

 

 

2.算法实现

int n = 4;//矩阵维数 //矩阵定义  struct Matrix {    ll ma[5][5];};int L,M;//矩阵乘法运算 取模 Matrix multi(Matrix a, Matrix b) {    Matrix ans;//存放结果矩阵     memset(ans.ma, 0, sizeof(ans.ma));    ll i, j, k;    for(i=1; i<=n; ++i)        for(j=1; j<=n; ++j)            for(k=1; k<=n; ++k)                ans.ma[i][j] = (ans.ma[i][j] + a.ma[i][k]*b.ma[k][j]%M) % M;    return ans;}//矩阵快速幂 取模 Matrix pow(Matrix a, ll x) {    Matrix ans;    memset(ans.ma, 0, sizeof(ans.ma));    ll i, j;    //单位阵初始化    for(i=1; i<=n; ++i)        ans.ma[i][i] = 1;            while(x) {        if(x & 1)            ans = multi(ans, a);        a = multi(a, a);                                 x >>= 1;    }    return ans;}

 

3.递推式的转移矩阵的构造

引例:斐波那契 递推公式 f(n) = f(n-1)  + f(n-2)

这里的转移矩阵是A矩阵,注意如果横着写f(n),f(n-1)那么A就放在后边,如果竖着写A就放在前面,一定要注意,竖前横后(书签很厚)。

 

一般性构造原理。先确定矩阵维数,对应矩阵相乘原则m*n矩阵要和n*k矩阵相乘才可以,把转移矩阵A的所有项全部设成未知数,然后根据转移方程式进行矩阵相乘,得到若干方程,令每个方程左右两边系数分别相等,就能求出所有未知数进而确定转移方程A。

快速构造矩阵: 从矩阵Sn,到矩阵Sn-1。逐行构造转移矩阵T,该行Ti与矩阵Sn-1的向量积为Sni。

 

【核心思想】答案矩阵里含有所有生成数据的基础,或者称为基元素,转移矩阵根据两个相邻的答案矩阵的转移构造。

 

4.例题 

 

根据前两种状态构造状态转移矩阵即可。

#include
#include
#include
#include
#define maxn using namespace std;typedef long long ll;int n = 4;struct Matrix { ll ma[5][5];};int L,M;Matrix multi(Matrix a, Matrix b) { Matrix ans; memset(ans.ma, 0, sizeof(ans.ma)); ll i, j, k; for(i=1; i<=n; ++i) for(j=1; j<=n; ++j) for(k=1; k<=n; ++k) ans.ma[i][j] = (ans.ma[i][j] + a.ma[i][k]*b.ma[k][j]%M) % M; return ans;} Matrix pow(Matrix a, ll x) { Matrix ans; memset(ans.ma, 0, sizeof(ans.ma)); ll i, j; for(i=1; i<=n; ++i) ans.ma[i][i] = 1; while(x) { if(x & 1) ans = multi(ans, a); a = multi(a, a); x >>= 1; } return ans;} int main(){ Matrix ans; while(cin>>L>>M) { if(L == 0){ cout<<0<
View Code

 

之前的题目都是点到点的状态转移,这道题是二维的,可以将其看成是列到列转移,构造转移矩阵时运用快速构造法。

#include
#include
#include
#include
#include
using namespace std;typedef long long ll;int n = 14;//矩阵维数 const ll M = 10000007;//矩阵定义 struct Matrix { ll ma[15][15];};//矩阵乘法运算 取模 Matrix multi(Matrix a, Matrix b) { Matrix ans;//存放结果矩阵 memset(ans.ma, 0, sizeof(ans.ma)); ll i, j, k; for(i=1; i<=n; ++i) for(j=1; j<=n; ++j) for(k=1; k<=n; ++k) ans.ma[i][j] = (ans.ma[i][j] + a.ma[i][k]*b.ma[k][j]%M) % M; return ans;}//矩阵快速幂 取模 Matrix qpow(Matrix a, ll x) { Matrix ans; memset(ans.ma, 0, sizeof(ans.ma)); ll i, j; //单位阵初始化 for(i=1; i<=n; ++i) ans.ma[i][i] = 1; while(x) { if(x & 1) ans = multi(ans, a); a = multi(a, a); x >>= 1; } return ans;}int N,m;int main(){ while(cin>>N>>m){ ll cnt = 1; ll num[15]; num[1] = 23; ll s; for(int i=1; i<=N; i++){ cin>>s; num[++cnt] = s; } num[cnt+1] = 3; if(N == 0 && m == 0){ cout<<0<
View Code

 

转载于:https://www.cnblogs.com/czsharecode/p/9674076.html

你可能感兴趣的文章
多线程通信的三大法器,你真的会用吗?
查看>>
Python爬虫--- 1.4 正则表达式:re库
查看>>
Xcode 10 升级导致项目报错的常见问题
查看>>
我们来说一说TCP神奇的40ms
查看>>
[LeetCode] 97. Interleaving String
查看>>
微服务架构组件分析
查看>>
Mongodb数据的导出与导入
查看>>
在SAP UI中使用纯JavaScript显示产品主数据的3D模型视图
查看>>
前端编码规范之:样式(scss)编码规范
查看>>
python 设计模式-适配器模式
查看>>
【Leetcode】82. 删除排序链表中的重复元素 II
查看>>
vue_music:排行榜rank中top-list.vue中样式的实现:class
查看>>
修改校准申请遇到的问题
查看>>
第一天·浏览器内核及Web标准
查看>>
Java版本兼容问题
查看>>
【DL-CV】浅谈GoogLeNet(咕咕net)
查看>>
【许晓笛】详解 EOS 的新共识机制 BFT-DPoS
查看>>
python大佬养成计划----win下对数据库的操作
查看>>
前端每日实战:125# 视频演示如何用纯 CSS 创作一个失落的人独自行走的动画...
查看>>
聊聊spring-data-redis的连接池的校验
查看>>