矩阵乘法优化dp
Posted shzr
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了矩阵乘法优化dp相关的知识,希望对你有一定的参考价值。
矩阵乘法优化dp
前几天学姐说要给我们考矩乘dp和期望dp...其实我们都(也可能只有我)不会。
那只能现学了,然而学了一天突然通知不考了qwq
矩阵乘法
A矩阵为m*k,B矩阵为k*n,两矩阵相乘则得C矩阵为m*n;
for (int i=1;i<=M;++i) for (int j=1;j<=N;++j) for (int k=1;k<=K;++k) c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
时间复杂度为$O(N^3)$,数学一本通上提到了一种奇妙的矩阵乘法$Strassen:O(N^{2.81})$,但是非常非常复杂非常非常难写,于是就不写了(而且我也不会);
矩阵快速幂
其实和数字快速幂的思想是一样的。有一个小技巧:如果一个矩阵的主对角线全为1,其他部分为0,对于另一个矩阵来说就相当于单位元,相乘不变;
矩阵快速幂:https://www.luogu.org/problemnew/show/P3390
# include <cstdio> # include <iostream> using namespace std; const int P=1e9+7; struct s { long long a[101][101]; }A,ans; long long k; int n; s mul(s a,s b) { s c; for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) c.a[i][j]=0; for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) for (int k=1;k<=n;k++) c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j]%P)%P; return c; } void qui (long long k) { while (k) { if(k&1) ans=mul(ans,A); A=mul(A,A); k=k>>1; } return ; } int main() { scanf("%d%lld",&n,&k); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) scanf("%lld",&A.a[i][j]); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) if(i==j) ans.a[i][j]=1; qui(k); for (int i=1;i<=n;i++) { for (int j=1;j<=n;j++) printf("%lld ",ans.a[i][j]); printf(" "); } return 0; }
矩乘优化数列递推
矩阵乘法可以用来加速线性的递推式(也许也可以加速别的递推吧),思路非常棒;
首先构造一列数列,保存与递推$f[n]$有关的项,以斐波那契数列为例:
$f[n]=f[n-1]+f[n-2]$ 所以构造的矩阵为
$egin{bmatrix}
f[n-1] \
f[n-2]
end{bmatrix}$
以上是关于矩阵乘法优化dp的主要内容,如果未能解决你的问题,请参考以下文章
bzoj4870: [Shoi2017]组合数问题(DP+矩阵乘法优化)
BZOJ 3326[Scoi2013]数数 数位dp+矩阵乘法优化