【算法学习】矩阵乘法
前言
特点:\(n\) 非常大 \(m\) 却非常小,求方案数,强制走 \(k\) 步的路径数。
当遇到数据范围极端地大时就可以考虑构造矩阵进行矩阵快速幂。
介绍
首先我们要知道矩阵的计算规则,两个矩阵 \(A\) 和 \(B\) 相乘,要求 \(A\) 的列数等于 \(B\) 的行数,\(A\) 的尺寸为 \(m\times n\),\(B\) 的尺寸为 \(n\times u\),那么乘积 \(C=m\times u\)。矩阵乘法C=AB的计算公式为 \(C[i,j]=\sum_{k=1}^{n} A[i][k]\times B[k][j]\)。代码为i,j,k三重循环。
for(int i=1;i<=m;i++){
for(int j=1;j<=u;j++){
for(int k=1;k<=n;k++){
c[i][j]=a[i][k]*b[k][j];
}
}
}
P5789 [TJOI2017] 可乐
这题是路径快速幂的模板题,问题有三种操作不动、动、自爆,我们用邻接矩阵存边,不动就是自己向自己存边,自爆就是每个点向 \(0\) 点连一条单向边,\(k\) 秒钟我们就对矩阵进行 \(k\) 次方即可。
快速幂你应该会写吧,开始要初始化为 \(1\),而矩阵相应的要初始化为单位矩阵(斜对角都是 \(1\) 的矩阵),最后统计答案 \(1\) 到所以点的方案数。
P1962 斐波那契数列
好了你已经学会了路径问题,那么接下来看看矩阵加速递推式,一看这题这不是斐波那契数列吗,直接写完一交发现TLE!!!一看数据范围(○´・д・)ノ,这时我们就要建模了!!!
https://www.luogu.com.cn/problem/solution/P1962
最后我们得到一个简单的矩阵就可以快速幂了后就可以得到答案了!!!
但其实矩阵的构造可以通过观察法观察出来,这个靠直觉吧。
P2886 [USACO07NOV] Cow Relays G
因为必须要经过n条边,大部分的最短路算法都没有用,所以考虑矩阵快速幂。
P5004 专心OI - 跳房子
矩阵快速幂的好题,发现数据非常大且为 dp 递推则考虑矩阵快速幂,先从部分分入手找规律。
\(m=1\)
N | ans |
---|---|
1 | 2 |
2 | 3 |
3 | 5 |
4 | 8 |
发现这不就是斐波那契数列吗,很好继续向下考虑。
\(m=2\)
N | ans |
---|---|
1 | 2 |
2 | 3 |
3 | 4 |
4 | 6 |
5 | 9 |
仔细一看递推式为 \(f_n=f_{n-1}+f_{n-3}\),感觉有点规律了,继续找。
\(m=3\)
N | ans |
---|---|
1 | 2 |
2 | 3 |
3 | 4 |
4 | 5 |
5 | 7 |
行了明白了,这个一看就是 \(f_n=f_{n-1}+f_{n-4}\),发现这递推式都大差不差的,那构造成矩阵是不是也差不多。
\(m=1 \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}\)
\(m=2 \begin{bmatrix} 1 & 0 & 1 \\ 1 & 0 & 0 \\ 0 & 1 & 0 \end{bmatrix}\)
\(m=3 \begin{bmatrix} 1 & 0 & 0 & 1 \\ 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \end{bmatrix}\)
发现左上和右上角总有 \(1\) 以及固定在左下的一条斜率为 \(-1\) 的全是 \(1\) 的长条,我们构造出来然后跑快速幂即可。
P5059 中国象棋
他说的是格点放置所以要聪明变通。
还是得建模,不过先要找到规律性质,但是正常不好找还是先 dp 找,设 \(f_{n,0/1}\) 为这个位置放/不放棋子的方案数,于是我们有
我们先不管一定要放 \(2\) 个的限制,我们最终的答案就是 \(sum=f_{n,0}+f_{n,1}\),但是这个式子好像可以拆啊,上面的式子代过来。
哎!这不是斐波那契数列吗,我们通过口算得到 \(ans_1=2,ans_2=3\),整体偏移了,答案就是 \(sum=fib_{n+2}\)。
那放两个就是要去除放一个的方案和不放的方案,因为这是直接加的递推所以直接减掉 \(n+1\) 即可。
那一共 \(n+1\) 行乘法原理直接快速幂即可,数据太大要么龟速乘要么高精度。