浅谈推矩阵加速推矩阵的方法

为什么要写这种不值得一提的东西

因为我太弱了

从最简单的斐波那契数列开始

第一步 确定递推

我们肯定是要先找到递推公式的,比如这个就是f[i]=f[i1]+f[i2]

第二步,写出当前矩阵和目标矩阵

采用宋氏矩阵分析法,我们写出所有的元素:

[f[i1]f[i2]](+1)[f[i]f[i1]]

第三步 确定转移矩阵的长宽

值得肯定的是,我们要构造的矩阵肯定是2×2的,毫无疑问

第四步 将转移矩阵中的一行拿出来与现有矩阵按位对比

对于没有出现在原始矩阵内的项(第一行)

我们一定是要利用到递推公式的,那么转移矩阵的系数一定与递推系数对应:1,1

对于原本就有的项(其他行)

我们通过操作0,1的存在就可以直接得到

实操

对于斐波那契数列数列写出的转移矩阵如下

[1110]

你已经很好的掌握了构造矩阵了,再做一点基础巩固练吧!

fn=a×fn1+b×fn2+c×fn3+d的转移矩阵

掌握了这个应该差不多能做大多数不太难的矩阵加速了

首先按照我们分析的步骤来,已经有递推了,那我们就先写出所有元素

[fn1fn2fn3d][fnfn1fn2d]

然后我们写出的转移矩阵肯定是4×4的对吧

最后再逐行分析

第一行显而易见:[a,b,c,1]
后面的也比较容易了,最后得到的就是这个:

[abc1100001000001]

最后再来一点矩阵快速幂就好了,记得一定要初始化矩阵哦,这里为了练习一下,就手写一下代码,出锅了不要骂呜呜呜

点击查看代码
struct Matrix{int n,m,a[maxn][maxn];Matrix(){memset(a,0,sizeof a);};}
Matrix operator*(Matrix a.Matrix b)
{
Matrix tmp;tmp.n=a.n,tmp.m=b.m;
for(int i=1;i<=a.n;i++)
{
for(int j=1;j<=b.m;j++)
{
int c=0;
for(int k=1;k<=a.m;k++)c+=a.a[i][k]*b.a[k][j];
tmp.a[i][j]=c;
}
}
return tmp;
}
Matrix base(int n)
{
Matrix tmp;tmp.n=tmp.m=n;
for(int i=1;i<=n;i++)tmp.a[i][i]=1;
return tmp;
}
Matrix Mpower(Matrix a,int b)
{
Matrix ans=base(a.n);
while(b)
{
if(b&1)ans=ans*a;
a=a*a;
b>>=1;
}
return ans;
}

当然可能也不止这一种情况

比如说推出的DP转移是这样的:f[i][j]=k=1nf[i1][k]×g[k][j]
容易发现这个转移方程酷似矩阵乘法,那么这个转移实际上是我们上述提到的情况的推广,因为显然,对于某个给定的 j ,转移方程里面各项的系数都是确定的,所以矩阵构造如下:(以 n=4 为例)

[f[1][1]f[1][2]f[1][3]f[1][4]]

[g[1][1]......g[1][4]g[2][1]......g[2][4]g[3][1]......g[3][4]g[4][1]......g[4][4]]

posted @   Hanggoash  阅读(45)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!
动态线条
动态线条end
点击右上角即可分享
微信分享提示