模板整理: 矩阵乘法


矩阵乘法是个灰常灰常有用的东西!
先是定义:

ABAnAmAAm=BnABAm=BnC=ABCn=AnCm=BmC(i,j)=A(i,k)B(k,j)

由此我们知道这是O( N3 )的,
似乎还有优化的,不过还是O( N3 )性价比高……
模板:

//val[N][N]存值,mod是模数,不需要时直接去掉即可
//重载了运算符,这样C++代码里更方便了
struct Matrix{
    int val[N][N];
    Matrix(){memset(val,0,sizeof(val));}
    Matrix operator *(Matrix x){
        Matrix c;
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++)
                for (int k=1;k<=n;k++)
                    c.val[i][j]=(c.val[i][j]+val[i][k]*x.val[k][j]%mod)%mod;
        return c;
    }
};


接下来就是它的应用,矩阵乘法我就只讲两个应用了:
1.图邻接矩阵的x次方。
例题:bzoj1898
对于一张图,构造一个邻接矩阵A,A(i,j)=1当i->j这条边存在,不然就是0,
那么令 B=Ax ,B(i,j)表示i走到j恰好走x步的路径数。
很有用的东西!……原理不是非常懂,只能大概说说,
就是矩阵乘法是 C(i,j)=A(i,k)B(k,j)
就是i走到某一个点k的方案数和k走到j的方案数用乘法原理计算起来就行了。
2.优化某些有限项dp。
例题:poj3734
比较经典的是斐波那契数列 fib(i)=fib(i1)+fib(i2)
因为不管i是多少,永远只和(i-1),(i-2)项有关,
所以可以考虑能否去构造一个矩阵A,使得A*(i,i-1,i-2)->(i+1,i,i-1)
(i,i-1,i-2)表示构造出i,i-1,i-2有关的矩阵,具体应该有很多种方法。
又比如 f[i][j]=f[i1][k]kki
由于i项只和(i-1)项有关,所以对第二维构造一个矩阵,
然后令某个矩阵和它相乘,固定地从(i-1)推到i,

矩阵乘法的过程直接快速幂就好了。

//z的初始化是令它为单位矩阵
Matrix ksm(Matrix a,int y){
    Matrix z;
    for (int i=1;i<=n;i++) z.val[i][i]=1;
    while (y){
        if (y&1) z=z*a;
        y>>=1;a=a*a;
    }
    return z;
}

猜你喜欢

转载自blog.csdn.net/ThinFatty/article/details/78485626