矩阵 重温
重温
详解:矩阵法 - cn是大帅哥886 - 博客园,这里仅仅简单过过基础。
矩阵乘:如 A*B=C,对于 C 某行某列的值,是 A 其中一行的每一个元素,和 B 其中一列的每一个元素,一一对应后根据二元组进行运算。
为啥是这样运算(一行和一列对应运算)?可以方便构造矩阵,从而优化递推啥的。
如 $(\times, +)$,就是乘起来后的和。也就是:$C_{i,j}=\sum\limits_{k=1}^{A.m} A_{i,k} \times B_{k, j}$,其中 $A.n$ 表示 A 矩阵的行数,$A.m$ 表示 A 矩阵的列数。
容易发现一些性质:
1.A 的列数=B的行数,不然对应不上
2.C的行数=A的行数,C的列数=B的列数,因为 C 的行数取决于 A 的行数,C 的列数列数取决于 B 的列数。
可以根据区间访问连续性优化
再然后矩阵快速幂和原板快速幂是一样的,我们重载乘号就好,注意把重载封装到结构体内,传入的参数是 B,原结构体内的参数是 A。运算顺序是不能换的,应该是 A*B 的顺序才行。
于是我们可以得出以下板子:
struct node
{
int n, m;
ll a[N][N];
void init(int n2, int m2, int isI)
{
n=n2, m=m2;
memset(a, 0, sizeof a);
for (int i=1; i<=n; i++) a[i][i]=isI;
}
node operator *(const node &B) const
{
node res;
res.init(n, B.m, 0);
for (int i=1; i<=n; i++)
for (int k=1; k<=m; k++)
for (int j=1; j<=B.m; j++)
res.a[i][j]=(res.a[i][j]+a[i][k]*B.a[k][j]%Mod)%Mod;
return res;
}
}mp, ans;
node qpow(node a, ll k)
{
node res;
res.init(a.n, a.m, 1);
while (k>0)
{
if (k&1) res=res*a;
a=a*a, k>>=1;
}
return res;
}
套路
1.何时用
1)是 DP 题,转移方程 f[i] 只和前 k 个状态有关,要求 f[n],且转移是线性的。其中 n 很大,k 很小。具体些就是 n>=1e9, k<=500
2)然后这个方程应该是常系数(如果系数有规律变化,分段处理,即分成若干个矩阵,分别处理)
以上,可以考虑矩阵快速幂优化。此时构造出大小为 k 的矩阵,然后快速幂优化就好。因此复杂度是 O(k^3logn)
2.怎么用
1.先推出 DP 转移方程
2.构造已知矩阵 A,所求矩阵 C 应该和已知矩阵 A 是一样的。所以为了转移,已知矩阵 A 所含的信息要能推出所求矩阵 C 的。如果推不出,就补条件。
这里已知矩阵 A 不应该包括系数在内,应该把系数放入未知矩阵 B 处理。
3.根据已知矩阵 A 和所求矩阵 C,确定未知矩阵 B 的大小,并用待定系数法求解未知矩阵 B。
4.利用矩阵快速幂就能做了,即 A*(B^K)=C。

浙公网安备 33010602011771号