OI模板 矩阵运算

OI模板 矩阵运算

矩阵乘法

const int N = 1, Mod = 1e9 + 7;
struct Matrix{
	int n, m;
	long long a[N][N];
	Matrix(int x, int y, int op) : n(x), m(y) {
		if(op >= 0){
			for(int i = 1; i <= n; ++ i)
				for(int j = 1; j <= m; ++ j)
					a[i][j] = op;
		} else if(op == -1){//单位矩阵 
			memset(a, 0, sizeof(a));
			for(int i = 1; i <= n; ++ i)
				a[i][i] = 1;
		}
	}
	Matrix() {}
	void read(int x, int y){
		n = x, m = y;
		for(int i = 1; i <= n; ++ i)
			for(int j = 1; j <= m; ++ j)
				scanf("%lld", &a[i][j]);
		return ;
	}
	void print(){
		for(int i = 1; i <= n; ++ i){
			for(int j = 1; j <= m; ++ j)
				printf("%lld ", a[i][j]);
			puts("");
		}
		return ;
	}
	Matrix operator * (const Matrix &b) const {
		Matrix c(n, b.m, 0);
		for(int i = 1; i <= n; ++ i)
			for(int j = 1; j <= b.m; ++ j)
				for(int k = 1; k <= m; ++ k)
					c.a[i][j] += a[i][k] % Mod * b.a[k][j] % Mod,
					c.a[i][j] = (c.a[i][j] + Mod) % Mod;
		return c;
	}
};

例题:Libre OJ #100. 矩阵乘法

矩阵快速幂

inline Matrix QuickPow(Matrix a, long long k){
	Matrix ans(a.n, a.n, -1);//初始化为单位矩阵
	while(k){
		if(k & 1) ans = ans * a;
		a = a * a;
		k >>= 1;
	}
	return ans;
}

另一种写法:

inline Matrix QuickPow(Matrix a, long long k){
	Matrix ans = a; -- k;
	while(k){
		if(k & 1) ans = ans * a;
		a = a * a;
		k >>= 1;
	}
	return ans;
}

例题:Luogu P3390 【模板】矩阵快速幂

矩阵加速线性递推式

斐波那契数列

F i b n = { 1   ( n ≤ 2 ) F i b n − 1 + F i b n − 2   ( n ≥ 3 ) Fib_n = \begin{cases} 1~(n\leq2) \\ Fib_{n-1}+Fib_{n-2}~(n \geq 3) \end{cases} Fibn={1 (n2)Fibn1+Fibn2 (n3)

[ F i b 2 F i b 1 ] × [ 1 1 1 0 ] n − 2 = [ F i b n F i b n − 1 ] \begin{bmatrix} Fib_{2}&Fib_{1} \end{bmatrix}\times\begin{bmatrix} 1&1 \\ 1&0 \end{bmatrix}^{n-2} = \begin{bmatrix} Fib_{n}&Fib_{n-1} \end{bmatrix} [Fib2Fib1]×[1110]n2=[FibnFibn1]

inline long long Fibonacci(long long k){
	if(k <= 2) return 1;
	Matrix Ans(1, 2, 0), Base(2, 2, 0);
	Ans.a[1][1] = Ans.a[1][2] = 1;
	Base.a[1][1] = Base.a[1][2] = Base.a[2][1] = 1;
	Base.a[2][2] = 0;
	return (Ans * QuickPow(Base, k - 2)).a[1][1]; 
}

例题:Luogu P1962 斐波那契数列

广义斐波那契数列

F i b n = { a 1   ( n = 1 ) a 2   ( n = 2 ) p ∗ F i b n − 1 + q ∗ F i b n − 2   ( n ≥ 3 ) Fib_n = \begin{cases} a_1~(n = 1) \\ a_2~(n = 2) \\ p * Fib_{n-1} + q * Fib_{n-2}~(n \geq 3) \end{cases} Fibn=a1 (n=1)a2 (n=2)pFibn1+qFibn2 (n3)

[ a 2 a 1 ] × [ p 1 q 0 ] n − 2 = [ F i b n F i b n − 1 ] \begin{bmatrix} a_{2}&a_{1} \end{bmatrix}\times\begin{bmatrix} p&1 \\ q&0 \end{bmatrix}^{n-2} = \begin{bmatrix} Fib_{n}&Fib_{n-1} \end{bmatrix} [a2a1]×[pq10]n2=[FibnFibn1]

例题:Luogu P1349 广义斐波那契数列

Luogu P1939 【模板】矩阵加速(数列)

a n = { 1   ( n ∈ { 1 , 2 , 3 } ) a n − 1 + a n − 3   ( n ≥ 4 ) a_n = \begin{cases} 1~(n\in \{1,2,3\}) \\ a_{n-1}+a_{n-3}~(n \geq 4) \end{cases} an={1 (n{1,2,3})an1+an3 (n4)

[ a 3 a 2 a 1 ] ∗ [ 1 1 0 0 0 1 1 0 0 ] n − 3 = [ a n a n − 1 a n − 2 ] \begin{bmatrix} a_3&a_2&a_1 \end{bmatrix} * \begin{bmatrix} 1&1&0 \\ 0&0&1 \\ 1&0&0 \end{bmatrix}^{n-3} = \begin{bmatrix} a_n&a_{n-1}&a_{n-2} \end{bmatrix} [a3a2a1]101100010n3=[anan1an2]

inline long long Getkth(long long k){
	if(k <= 3) return 1;
	Matrix Ans(1, 3, 0), Base(3, 3, 0);
	Ans.a[1][1] = Ans.a[1][2] = Ans.a[1][3] = 1;
	Base.a[1][1] = Base.a[1][2] = Base.a[2][3] = Base.a[3][1] = 1;
	return (Ans * QuickPow(Base, k - 3)).a[1][1]; 
}

矩阵加速 DP

一张有向图求某点到另外一点定长路线 k k k 的方案数

邻接矩阵的 k k k 次方就为答案,第 i , j i,j i,j 位的数字表示点 i i i 到点 j j j 长度为 k k k 的路径数。

如果有原地踏步增加边 ( i , i ) (i,i) (i,i),有停止增加边 ( i , 0 ) (i,0) (i,0)

例题:Luogu P5789 [TJOI2017]可乐(数据加强版)

一张有向图求某点到另外一点定长路线 k k k 的最小花费

将矩阵乘法中乘法一句换为 c.a[i][j] = min(c.a[i][j], a[i][k] + b.a[k][j]);,邻接表以及乘法中 c c c 数组初始化为 inf ⁡ \inf inf 即可。

邻接矩阵的 k k k 次方就为答案,第 i , j i,j i,j 位的数字表示点 i i i 到点 j j j 长度为 k k k 的最小花费。

例题:Luogu P2886 [USACO07NOV]Cow Relays G

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值