【小白学算法】矩阵快速幂超详细解析+例题[HDU - 2802]

news/2025/9/21 18:02:42/文章来源:https://www.cnblogs.com/clyc-ngc/p/19103911

用于高效解决线性递推问题

前言

在算法竞赛和实际编程中,我们经常遇到需要计算矩阵的高次幂的问题。如果直接用朴素的矩阵乘法来计算,时间复杂度会达到O(n³ × k),其中n是矩阵的维度,k是幂次。当k非常大时(比如\(10^9\)),这样的时间复杂度是无法接受的。矩阵快速幂就是为了解决这个问题而诞生的算法。

什么是矩阵快速幂?

矩阵快速幂就是快速幂算法再矩阵运算中的应用。它基于这样的思想:

\(A^8\) = \((( A^2 )^2)^2\)

\(A^9\)=\(A × A^8\)

通过将指数进行二进制分解,我们可以在O(log k)次矩阵乘法内计算出\(A^k\)

快速幂基本原理

以计算a^n为例:

  • 如果n是偶数:\(a^n\) = \((a^{n/2})^2\)

  • 如果n是奇数:\(a^n\) = a ×$ a^{n-1}$

这个过程可以用递归或迭代实现。

矩阵快速幂的实现步骤

矩阵定义

struct matrix {int mat[6][6];void init() {memset(mat, 0, sizeof(mat));}
};

矩阵乘法

由于幂的过程中,我们要实现一个矩阵的乘法,所以首先要将矩阵乘法写出;

matrix mul(matrix a, matrix b) {   //return a*bmatrix c;c.init();for (int i = 0; i < 6; i++) {for (int j = 0; j < 6; j++) {for (int k = 0; k < 6; k++) {c.mat[i][j] += ((a.mat[i][k] % mod) * (b.mat[k][j] % mod)) % mod;c.mat[i][j] %= mod;}}}return c;
}

矩阵快速幂

matrix fast_pow(matrix A, int n) {   //return A^n%modmatrix B;B.init();for (int i = 0; i < 6; i++) {   //单位矩阵B.mat[i][i] = 1;}while (n) {if (n & 1) {B = mul(B, A);}A = mul(A, A);n >>= 1;}return B;
}

例题HDU - 2802

本题就是根据递推公式,求其中的某一项即F(n),那么可以用矩阵快速幂来解决此题(本题还可以打表找出规律求解,这里只介绍矩阵快速幂方法^^)

在写之前先求出转移矩阵是此题的关键

递推式化简:

\(F(N)=F(N−2)+N^3−(N−1)^3\)

展开:

\(N^3−(N−1)^3=3*N^2−3*N+16\)

所以:

\(F(N)=F(N−2)+3*N^2−3*N+1\)

状态向量构造:

我们需要同时存$ F(N)\(,以及和 N 相关的多项式项(\)N_2\(, N, 常数)。 因为转移里有\) F(N−2)$,所以状态至少要带上 \(F(N)\),\(F(N−1)\)

定义:

\[S(n) = \begin{bmatrix} F(n) \\ F(n-1) \\ n^2 \\ n \\ 1 \end{bmatrix}\]

转移矩阵:

根据递推式:

\(F(N)=F(N−2)+3*N^2−3*N+1\)

所以:

  • \(F(N)\) 依赖 \(F(N−2)\),而$ F(N−2) $就是上一步向量里的第二维。

  • 多项式部分直接线性组合 \(N_2\),\(N\),1。

然后要写出矩阵,把 \(S(N)\) 表达为 \(M⋅S(N−1)\)

完整代码

#include <iostream>
#include <cstring>
#define int long long
using namespace std;const int mod = 2009;struct matrix {int mat[6][6];void init() {memset(mat, 0, sizeof(mat));}
};matrix mul(matrix a, matrix b) {   //return a*bmatrix c;c.init();for (int i = 0; i < 6; i++) {for (int j = 0; j < 6; j++) {for (int k = 0; k < 6; k++) {c.mat[i][j] += ((a.mat[i][k] % mod) * (b.mat[k][j] % mod)) % mod;c.mat[i][j] %= mod;}}}return c;
}matrix fast_pow(matrix A, int n) {   //return A^n%modmatrix B;B.init();for (int i = 0; i < 6; i++) {   //单位矩阵B.mat[i][i] = 1;}while (n) {if (n & 1) {B = mul(B, A);}A = mul(A, A);n >>= 1;}return B;
}signed main() {int N;while (cin >> N && N) {if (N == 1) {cout << 1 % mod << "\n";continue;}if (N == 2) {cout << 7 % mod << "\n";continue;}// 状态向量: [F(n), F(n-1), n^2, n, 1, dummy]// 6维里最后一个可以闲置// 我们要求 F(N),利用矩阵快速幂推到目标// 转移矩阵 M: S(k) -> S(k+1)matrix M;M.init();// F(k+1) = F(k-1) + 3(k+1)^2 - 3(k+1) + 1// => 依赖 F(k-1) 以及 (k+1)^2, (k+1), 1// 这里直接手写对应项// [F(k+1)] = [0 1 3 -3 1 0] * S(k)// [F(k)]   = [1 0 0 0 0 0] * S(k)// [ (k+1)^2 ] = 转移自 N^2, N, 1// [ (k+1) ]   = ...// [ 1 ]       = [0 0 0 0 1 0]M.mat[0][1] = 1;  // F(k-1)M.mat[0][2] = 3;  // +3*N^2M.mat[0][3] = 3; // -3*NM.mat[0][4] = 1;  // +1M.mat[1][0] = 1;  // F(k)// (k+1)^2 = N^2 + 2N + 1M.mat[2][2] = 1;M.mat[2][3] = 2;M.mat[2][4] = 1;// (k+1) = N + 1M.mat[3][3] = 1;M.mat[3][4] = 1;M.mat[4][4] = 1; // 常数项保持 1// 取模修正负数for (int i = 0; i < 6; i++) {for (int j = 0; j < 6; j++) {M.mat[i][j] = (M.mat[i][j] % mod + mod) % mod;}}// 初始状态 S(2)int S[6] = {7, 1, 4, 2, 1, 0}; // [F(2)=7, F(1)=1, 2^2=4, 2, 1, 0]// 快速幂:从 S(2) 推到 S(N)matrix P = fast_pow(M, N - 2);// 结果向量 = P * Sint ans[6] = {0};for (int i = 0; i < 6; i++) {for (int j = 0; j < 6; j++) {ans[i] = (ans[i] + P.mat[i][j] * S[j]) % mod;}}cout << ans[0] % mod << "\n"; // F(N)}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/908939.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

lyms 的神秘歌单

关于这个闲话。还有 50 min 就要回 whk 了,我们可以干点什么呢?wy_x and lyms : 写闲话!所以就写。 说实在的根本不知道能写什么。 要不然给自己喜欢的曲子列个列表。 就当是什么神秘歌单了。 update on 9.21 推什么…

大学园区二手书交易强大的平台(代码+数据库+LW)

大学园区二手书交易强大的平台(代码+数据库+LW)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas",…

深入解析:SpringMVC的请求接收与结果响应

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Element UI框架中自定义input组件的placeholder样式

Element UI是基于Vue.js的组件库,提供了一系列的组件,方便在Vue应用程序中快速使用。对于自定义input组件的placeholder样式,可以通过CSS覆盖默认样式来实现。以下是对Element UI中input组件的placeholder样式自定义…

go语言数组的方法

go语言数组的方法 漫思

【C++】类与结构体的区别

区别 技术上 实际上类与结构体在技术层面除了可见性并没有区别,唯一值得一提的区别就是: class类默认情况下其中的变量、函数都为private私有的。 struct结构体默认情况下则都是public公共的。 用法上 何时使用class…

Linux云端服务器上部署Spring Boot应用

在Linux云服务器上部署Spring Boot应用环境准备:确保Java JDK已安装。Spring Boot通常需要Java 8或更高版本。使用 java -version来确认Java版本。 安装Maven(如果是Maven项目)或Gradle(如果是Gradle项目),这取决…

HTML表单验证:确认input元素输入为具有特定整数和小数位数的数值

为了确保HTML表单中的 input元素接收具有特定整数位和小数位数的数值,您需要利用HTML和JavaScript进行前端验证。在HTML5中,可以使用内建的表单验证功能,比如 pattern属性,然而 pattern属性主要用于字符串的正则表…

课前问题思考3

1.什么样的方法应该用static修饰?不用static修饰的方法往往具有什么特性?Student的getName应该用static修饰吗?什么样的方法应该用static修饰?方法不依赖于类的实例状态。 方法提供的功能与类的实例无关。 工具类方…

实用指南:Docker部署Drawnix开源白板工具

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

go静态方法

go静态方法 漫思

在CentOS上配置SVN至Web目录的自动同步

配置SVN(Subversion)到Web目录的自动同步在CentOS系统中是一种有效的代码部署方法,它可以让团队成员更便捷地管理和发布Web项目。以下是如何在CentOS上实现SVN仓库到Web目录的自动同步的详细步骤。= 1. 安装并配置S…

AIGC在游戏开发中的革命性影响:从生产效率到体验创新 - 详解

AIGC在游戏开发中的革命性影响:从生产效率到体验创新 - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Cons…

使用Docker配置并连接HBase的Java API

配置并使用Docker容器化HBase,并通过Java API进行连接,首先涉及到Docker配置HBase环境以及编写Java代码以编程方式连接HBase。以下是这一流程的具体步骤。 使用Docker部署HBase获取HBase镜像:使用Docker Hub提供的官…

在Linux环境下安装和卸载DMETL5数据迁移工具

在Linux环境下,安装和卸载特定的数据迁移工具,如DMETL5,通常涉及到一系列具体步骤。由于DMETL5不是一个广泛认知的公共软件,我们可以遵循一般的Linux软件安装和卸载流程来讨论这个问题。 安装DMETL5数据迁移工具 通…

赛前训练3 欧拉路

以下,斜体表示注意点,粗体表示技巧点。 无向图欧拉路径的判定:除去孤点之外图联通。度数为奇数的点只有 \(0\) 或 \(2\) 个。有向图欧拉路径的判定:除去孤点之外图联通。出度比入度大一或入度比出度大一的有 \(0\)…

HDFS 纠删码技术(Erasure Coding, EC)详解 - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

SQL小贴式: 用NOT EXISTS 而不是 NOT IN !!!

SQL小贴式: 用NOT EXISTS 而不是 NOT IN !!! 当使用NOT IN进行过滤时, 比如NOT IN xxx 时, 如果 xxx 中有NULL值时, 就会一行也不返回 !在 SQL 中,NOT IN 子查询遇到 NULL 值时会产生意外行为,主要因为 SQL 使用三值…

CF global round 29 CD

CF global round 29 CDCF global round 29 C 思路: 只要考虑每个 0 的位置怎么更新 考虑从当前 pos[i] 转移到下一个 pos[i+1] 的位置 分三种情况, 中间没有 1, 只要当前位置有一个位置左右两种情况都能转移 中间 1…

go语言复杂的map

go语言复杂的map 漫思