矩阵法
前言
自我感觉矩阵法在优化动态规划时的实质就是在转移上的优化;
对于转移数量多且重复的操作可以打包进行加速。
在构造矩阵时想好矩阵每一位的值的意义和总转移次数。
别固向思维,矩阵快速幂可以进行多次,不一定只矩阵快速幂一次。
前置知识
1.矩阵乘法
2.快速幂(此处不讲)
矩阵
简单介绍
矩阵可以看成一个
这就是个
【单位矩阵】
单位矩阵的性质就是任意一个矩阵合法乘以一个单位矩阵,不改变矩阵的值,其作用相当于整数
矩阵加速的应用
① 线性递推
② 动态规划优化
③ 图论
讲解的定义
接下来的讲解会用到两个矩阵
现在定义
矩阵加法
【前提】
相加的两个矩阵
【加法原则】
然后就是基本的对位相加,不多作解释。
矩阵乘法
【前提】
相加的两个矩阵
【乘法原则】
小技巧:记住
这里的乘法我们需要用到重载运算符,代码如下:
inline Matrix operator * (const Matrix &A,const Matrix &B) {
Matrix C;
int Ax,Ay,Bx,By;
Ax=n,Ay=Bx=n,By=n;
for(int i=1;i<=Ax;i++) {
for(int j=1;j<=By;j++) {
for(int k=1;k<=Ay;k++)
C.dat[i][j]=(C.dat[i][j]+(A.dat[i][k]%mod)*(B.dat[k][j]%mod)%mod)%mod;
}
}
return C;
}举个小栗子:
转移方程是
那么从
矩阵
矩阵
那么矩阵
再把矩阵
矩阵
即对于
这里如果我们需要求出
在构造矩阵做草稿的时候可以把
满足的【乘法运算】
矩阵乘法满足乘法结合律,乘法分配律;
但不满足乘法交换律!!!
矩阵快速幂
struct Matrix {
unsigned long long dat[N][N];
Matrix() {
for(int i=1;i<N;i++) {
for(int j=1;j<N;j++)
dat[i][j]=0;
}
}
inline void build() {
for(int i=1;i<=3;i++)
dat[i][i]=1;
return ;
}
};
inline Matrix operator * (const Matrix &A,const Matrix &B) {
Matrix C;
int Ax,Ay,Bx,By;
Ax=3,Ay=Bx=3,By=3;
for(int i=1;i<=Ax;i++) {
for(int j=1;j<=By;j++) {
for(int k=1;k<=Ay;k++)
C.dat[i][j]=(C.dat[i][j]+(A.dat[i][k]%m)*(B.dat[k][j]%m)%m)%m;
}
}
return C;
}
inline Matrix Mqpow(Matrix a,int p) {
Matrix res;
res.build();
while(p) {
if(p&1)
res=res*a;
a=a*a,p>>=1;
}
return res;
}关于常数优化
小技巧:在不改变答案贡献的前提下改变状态转移,以保证内存访问是连续的。
解释
简单讲讲,就假设现在有转移方程为
那改一改转移式子为
矩阵乘法上的应用
这里矩阵乘法时将