【蓝桥杯Java组】一学就会的小技巧(五):矩阵快速幂

header

🍎前言:

🏅🏅前面已经介绍了快速幂这个技巧,快速幂除了可以拓展出龟速乘外,还可以用于计算矩阵的幂。矩阵快速幂在学会了快速幂的情况下很好掌握,只需要在矩阵乘法的基础上套一个快速幂模板就可以了。

题目传送门🚀🚀🚀

题目链接
P3390 【模板】矩阵快速幂https://www.luogu.com.cn/problem/P3390

🍬矩阵快速幂:

题目

👩🏻‍🏫如果你忘记了矩阵乘法,可以先来回顾一下~

  • 对于矩阵matrixA[n][p]matrixB[p][m] m a t r i x A × m a t r i x B matrixA \times{matrixB} matrixA×matrixB可以得到一个新的矩阵matrixC[n][m]

  • 矩阵的乘法不满足交换律,即 m a t r i x A × m a t r i x B matrixA \times matrixB matrixA×matrixB不等于 m a t r i x B × m a t r i x A matrixB \times matrixA matrixB×matrixA

  • 两个矩阵可以相乘的条件是:前一个矩阵的列数与后一个矩阵的行数相等。

  • 矩阵乘法的规则:

    百度百科

    简言之就是前行乘后列。

🍦矩阵乘法代码模板(Java):

public static long[][] matrixMultiply(long[][] matrixA, long[][] matrixB) {
	int n = matrixA.length, p = matrixB.length, m = matrixB[0].length;
	if (p != matrixA[0].length)
		return null;
	long[][] res = new long[n][m];
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
			for (int k = 0; k < p; k++)
				res[i][j] += matrixA[i][k] * matrixB[k][j];
	return res;
}

👩🏻‍🏫题目要我们求矩阵的n次幂,只需要将快速幂模板里的普通乘法改为矩阵乘法,结果是一个n阶方阵 m a t r i x C [ n ] [ n ] matrixC[n][n] matrixC[n][n]

⭐需要注意的是矩阵快速幂中的结果初始值要设置为单位矩阵。

👉🏻什么是单位矩阵?

在矩阵的乘法中,有一种矩阵起着特殊的作用,如同数的乘法中的1,这种矩阵被称为单位矩阵。它是个方阵,从左上角到右下角的对角线(称为主对角线)上的元素均为1。除此以外全都为0。

单位矩阵

🍦AC代码(C语言):

#include<iostream>

using namespace std;

typedef long long ll;

const ll m = 1e9 + 7;

ll n;
ll p;
ll matrix[105][105];
ll res[105][105] = {0};

void mult1() {
    ll temp[105][105] = {0};
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            for (int k = 0; k < n; k++)
                temp[i][j] = (temp[i][j] + matrix[i][k] * matrix[k][j]) % m;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            matrix[i][j] = temp[i][j];
}

void mult2() {
    ll temp[105][105] = {0};
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            for (int k = 0; k < n; k++)
                temp[i][j] = (temp[i][j] + res[i][k] * matrix[k][j]) % m;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            res[i][j] = temp[i][j];
}

int main() {
    scanf("%lld %lld", &n, &p);
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            scanf("%lld", &matrix[i][j]);
    for (int i = 0; i < n; i++)
        res[i][i] = 1;
    while (p > 0) {
        if (p & 1 == 1)
            mult2();
        mult1();
        p = p >> 1;
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
                printf("%lld ", res[i][j] % m);
        }
        printf("\n");
    }
    return 0;
}
  • temp[i][j] = (temp[i][j] + res[i][k] * matrix[k][j]) % m这条语句写成temp[i][j] += res[i][k] * matrix[k][j] % m提交到洛谷的OJ上过不了任何样例,算是个小坑吧,排查了好久~

  • 试着用Java写了一下,提交上去直接RE了,本地调试没有任何问题,和C语言的输出结果都是一样的(无语)🙃

🍦Java模板代码:

import java.util.Scanner;

public class Main {

    public static final long mod = 1000000007;

    public static long[][] matrixMultiply(long[][] matrixA, long[][] matrixB) {
        int n = matrixA.length, p = matrixB.length, m = matrixB[0].length;
        if (p != matrixA[0].length)
            return null;
        long[][] ans = new long[n][m];
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++) {
                for (int k = 0; k < p; k++)
                    ans[i][j] += (matrixA[i][k] % mod) * (matrixB[k][j] % mod) % mod;
			ans[i][j] = ans[i][j] % mod;
            }
        return ans;
    }

    public static long[][] fastMatrixPow(long[][] matrix, long k) {
        int len = matrix.length;
        long[][] res = new long[len][len];
        for (int i = 0; i < len; i++)
            res[i][i] = 1;
        while (k > 0) {
            if ((k & 1) == 1)
                res = matrixMultiply(res, matrix);
            matrix = matrixMultiply(matrix, matrix);
            k = k >> 1;
        }
        return res;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        long k = sc.nextInt();
        long[][] matrix = new long[n][n];
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                matrix[i][j] = sc.nextInt();
        sc.close();
        long[][] res = fastMatrixPow(matrix, k);
        for (int i = 0; i < n; i++) {
            if (i != 0)
                System.out.println("");
            for (int j = 0; j < n; j++)
                System.out.print(res[i][j] % mod + " ");
        }
    }
}

🍌🍌🍌
本文介绍了第五个小技巧——矩阵快速幂,洛谷的OJ上提交我的Java版代码直接Runtime Error,C语言倒是可以过,但是赋值语句a = a+b写成a+=b过不了样例,如果你知道为什么,欢迎在评论区留言~
🍍🍍🍍
创作不易,如果觉得本文对你有所帮助的话请动动小手,给博主点个免费的赞吧。🙇🏻‍♀️
🍉🍉🍉
@作者:Mymel_晗,计科专业大学牲一枚,请大佬们多多关照~

footer

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mymel_晗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值