矩阵 重温

重温


详解:矩阵法 - 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。

 

posted @ 2025-06-11 13:29  cn是大帅哥886  阅读(11)  评论(0)    收藏  举报