zoukankan      html  css  js  c++  java
  • 矩阵乘法学习笔记

    矩阵是一个数学阵列。

    概念

    一个 $m$ 行 $n$ 列的矩阵 $A$ 可以表示为:
    $$
    A=
    egin{bmatrix}
    a_{11} & a_{12} & cdots & a_{1n} \
    a_{21} & a_{22} & cdots & a_{2n} \
    cdots & cdots & & cdots \
    a_{m1} & a_{m2} & cdots & a_{mn} \
    end{bmatrix}
    $$
    这是一个 $m imes n$ 矩阵。

    在这里,我们定义数组第一维为行号,第二维为列号,a[i][j] 表示矩阵第 $i$ 行第 $j$ 列的数。

    矩阵乘法

    当且仅当,第一个矩阵列数与第二个矩阵行数相等时,才可以将两者相乘。

    设 $A$ 是 $m imes p$ 矩阵,$B$ 是 $p imes n$ 矩阵,则 $C = A imes B$ 是 $m imes n$ 矩阵。

    其中 $C_{ij}$ 为 $A$ 第 $i$ 行第一个乘以 $B$ 第 $j$ 列第一个,加上 $A$ 第 $i$ 行第二个乘以 $B$ 第 $j$ 列第二个 …… 一直加到 $A$ 第 $i$ 行第 $p$ 个乘以 $B$ 第 $j$ 列第 $p$ 个。即:
    $$
    egin{aligned}
    forall i in [1, m], j in [1, n] \
    C_{ij} = sum_{k=1}^{p} A_{ik} imes B_{kj}
    end{aligned}
    $$
    直接模拟即可。

    性质

    矩阵乘法满足结合律和分配律:
    $$
    egin{aligned}
    (A imes B) imes C = A imes (B imes C)\
    A imes C + B imes C = (A + B) imes C
    end{aligned}
    $$
    不满足交换律:
    $$
    A imes B ot= B imes A
    $$

    矩阵快速幂

    根据矩阵乘法的性质,利用乘法结合律,基于快速幂可以快速求出 $A^n$。

    模板

    Luogu 3390

    给定 $n imes n$ 的矩阵 $A$,求 $A^k$。

    #include <cstdio>
    #include <cstring>
    
    typedef long long ll;
    
    const int maxn = 105;
    const int P = 1e9 + 7;
    
    ll a[maxn][maxn];
    ll t[maxn][maxn]; // t 为临时变量
    ll ans[maxn][maxn];
    
    void addToAns(int n) {
    	memcpy(t, ans, sizeof(ans));
    	memset(ans, 0, sizeof(ans));
    	for (int i = 1; i <= n; i++) {
    		for (int j = 1; j <= n; j++) {
    			for (int k = 1; k <= n; k++) {
                    // ans = ans * a
    				ans[i][j] = (ans[i][j] + (t[i][k] * a[k][j]) % P) % P;
    			}
    		}
    	}
    }
    
    void mulSelf(int n) {
    	memcpy(t, a, sizeof(a));
    	memset(a, 0, sizeof(a));
    	for (int i = 1; i <= n; i++) {
    		for (int j = 1; j <= n; j++) {
    			for (int k = 1; k <= n; k++) {
                    // a = a * a
    				a[i][j] = (a[i][j] + (t[i][k] * t[k][j]) % P) % P;
    			}
    		}
    	}
    }
    
    int main() {
    	int n;
    	ll k;
    	scanf("%d %lld", &n, &k);
    	for (int i = 1; i <= n; i++) {
    		for (int j = 1; j <= n; j++) {
    			scanf("%lld", &a[i][j]);
    			ans[i][j] = a[i][j];
    		}
    	}
    	k = k - 1;
    
    	while (k) {
    		if (k & 1) addToAns(n);
    		mulSelf(n);
    		k >>= 1;
    	}
    
    	for (int i = 1; i <= n; i++) {
    		for (int j = 1; j <= n; j++) {
    			printf("%lld ", ans[i][j]);
    		}
    		printf("
    ");
    	}
    
    	return 0;
    }
    

    例题

    POJ 3070

  • 相关阅读:
    打造基于CentOS7的xfce最简工作环境
    Linux下C程序的编辑,编译和运行以及调试
    修正 XE6 TListView 上方 SearchBok 右边的清除钮显示
    TabControl 显示彩色的图示 (XE6 Firemonkey)
    TSwitch 中文简繁显示支持(XE6 Android)
    改变 TMemo 的背景颜色 (Firemonkey)
    修正 XE5 Android 键盘三个问题
    Delphi 收藏
    展示 Popup 的使用方法
    ListView 下拉更新 (支持 Android)
  • 原文地址:https://www.cnblogs.com/lcfsih/p/14391371.html
Copyright © 2011-2022 走看看