矩阵乘法优化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的主要内容,如果未能解决你的问题,请参考以下文章

形态形成场(矩阵乘法优化dp)

bzoj4870: [Shoi2017]组合数问题(DP+矩阵乘法优化)

BZOJ 3326[Scoi2013]数数 数位dp+矩阵乘法优化

LightOJ 1268 Unlucky Strings(KMP+矩阵乘法+基础DP)

矩阵乘法加速图上问题专题总结

ZJOI2005沼泽鳄鱼