矩阵快速幂 poj3070 3233 3735 3150

一、矩阵的基础知识

1.结合性 (AB)C=A(BC).

2.对加法的分配性 (A+B)C=AC+BCC(A+B=CA+CB 

3.对数乘的结合性 k(AB=kA)B =A(kB).

4.关于转置 (AB)'=B'A'

一个矩阵就是一个二维数组,为了方便声明多个矩阵,我们一般会将矩阵封装一个类或定义一个矩阵的结构体,我采用的是后者。

最特殊的矩阵应该就是单位矩阵e了,它的对角线的元素为1,非对角线元素为0。一个n*n的矩阵的0次幂就是单位矩阵。

若A为n×k矩阵,B为k×m矩阵,则它们的乘积AB(有时记做A·B)将是一个n×m矩阵。其乘积矩阵AB的第i行第j列的元素为:

一般矩阵乘法采用朴素的O(n^3)的算法,但是对于一些比较稀疏的矩阵(就是矩阵中0比较多),对于这样的矩阵我们可以采用矩阵的优化,这个算法也适用于一般的矩阵,0特别多时,复杂度可能会降低到O(n^2),实现如下:

还要注意的是,我们要尽可能的减少取模运算,因为取模的复杂度很高,这样我们就可以节约时间了。

矩阵加法就是简单地将对应的位置的两个矩阵的元素相加。

我们一般考虑的是n阶方阵之间的乘法以及n阶方阵与n维向量(把向量看成n×1的矩阵)的乘法。矩阵乘法最重要的性质就是满足结合律,同时它另一个很重要的性质就是满足交换率,这保证了矩阵的幂运算满足快速幂取模(A^k % MOD)算法,矩阵快速幂其实就是二分指数,避免重复的计算。我们可以采用递归的方式很容易的写出来,但是当指数比较大,或者矩阵比较大得时候,我们就会出现栈溢出的状况,不断RE(我就被坑过)。所以还是写成迭代的方式比较好。

制作矩阵图一般要遵循以下几个步骤: 

1、列出质量因素: 

2、把成对对因素排列成行和列,表示其对应关系 

3、选择合适的矩阵图类型 

4、在成对因素交点处表示其关系程度,一般凭经验进行定性判断,可分为三种:关系密切、关系较密切、关系一般(或可能有关系),并用不同符号表示 

5、根据关系程度确定必须控制的重点因素 

6、针对重点因素作对策表。

二、矩阵快速幂的应用

7、poj3070 是求解菲波那切数列,f(n)=f(n-1)+f(n-2),如果我们一个个递推求解,当n特别大的时候复杂度就会变的很高,对于f(n)= a*f(n-1

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是Java解决POJ3233矩阵序列问题的代码和解释: ```java import java.util.Scanner; public class Main { static int n, k, m; static int[][] A, E; public static void main(String[] args) { Scanner sc = new Scanner(System.in); n = sc.nextInt(); k = sc.nextInt(); m = sc.nextInt(); A = new int[n][n]; E = new int[n][n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { A[i][j] = sc.nextInt() % m; E[i][j] = (i == j) ? 1 : 0; } } int[][] res = matrixPow(A, k); int[][] ans = matrixAdd(res, E); printMatrix(ans); } // 矩阵乘法 public static int[][] matrixMul(int[][] a, int[][] b) { int[][] c = new int[n][n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { for (int k = 0; k < n; k++) { c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % m; } } } return c; } // 矩阵快速幂 public static int[][] matrixPow(int[][] a, int b) { int[][] res = E; while (b > 0) { if ((b & 1) == 1) { res = matrixMul(res, a); } a = matrixMul(a, a); b >>= 1; } return res; } // 矩阵加法 public static int[][] matrixAdd(int[][] a, int[][] b) { int[][] c = new int[n][n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { c[i][j] = (a[i][j] + b[i][j]) % m; } } return c; } // 输出矩阵 public static void printMatrix(int[][] a) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { System.out.print(a[i][j] + " "); } System.out.println(); } } } ``` 解释: 1. 首先读入输入的n、k、m和矩阵A,同时初始化单位矩阵E。 2. 然后调用matrixPow函数求出A的k次矩阵res。 3. 最后将res和E相加得到结果ans,并输出。 4. matrixMul函数实现矩阵乘法,matrixPow函数实现矩阵快速幂,matrixAdd函数实现矩阵加法,printMatrix函数实现输出矩阵
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值