codevs1281 矩阵乘法 快速幂 !!!手写乘法取模!!! 练习struct的构造函数和成员函数

本文深入探讨了一道关于矩阵快速幂的编程题目的实现细节。包括矩阵乘法、快速幂算法的具体实现过程,以及如何处理数值溢出等问题。文章还特别强调了在矩阵运算中需要注意的一些细节,例如初始化矩阵的方式等。
  对于这道题目以及我的快速幂以及我的一节半晚自习我表示无力吐槽,,

  首先矩阵乘法和快速幂没必要太多说吧,,嗯没必要,,我相信没必要,,实在做不出来写两个矩阵手推一下也就能理解矩阵的顺序了,要格外注意一些细节,比如快速幂时ans矩阵的初始化方式,快速幂的次数,矩阵乘法过程中对临时矩阵的清零,最后输出结果时的初始矩阵。。。矩阵快速幂好理解但是细节还是有点小坑的。。

  下面就是满满的槽点,,高能慎入!!!

 


 

 

  对于这个题目要求矩阵过程中对m取模,结果对g取模,我表示难以接受,,上来没看清题直接wa19个点,另,经本人实测,在矩阵中直接对m和g取模会直接挂掉,

  历经千辛万苦终于改对之后,,发现wa了3个点,,经过eirlys(某坑货)的提示发现过程中乘法会爆long long,于是便一脸mb,脑抽的改成unsign long long后依旧过不了,认真的去看了题解,,然后整个人就呵呵哒了,,题解告诉我要手写快速乘法。。。。。。

  真是够了。。。。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 
 5 
 6 struct data {
 7     long long f[3][3];
 8     data (void) {
 9         memset(f, 0, sizeof(f));
10         f[0][0] = 1;
11         f[1][1] = 1;
12         f[2][2] = 1;
13     }
14     void clear(void) {
15         memset(f, 0, sizeof(f));
16     }
17     void print(void) {
18         for (int i = 0; i < 3; i++) {
19             for (int j = 0; j < 3; j++) printf("%lld ", f[i][j]);
20             printf("\n");
21         }
22         printf("\n");
23     }
24 };
25 
26 long long m, a, c, x0, n, g;
27 data cur;
28 
29 long long mu (long long a1, long long a2) {
30     long long ans = 0;
31     while (a2 > 0) {
32         if (a2 & 1) ans = (ans + a1) % m;
33         a1 = (a1 + a1) % m;
34         a2 >>= 1;
35     }
36     return (ans);
37 }
38 
39 data operator * (data a1, data a2) {
40     data t;
41     t.clear();
42     for (int i = 0; i < 3; i++)
43         for (int j = 0; j < 3; j++) 
44             for (int k = 0; k < 3; k++) {
45                 t.f[i][j] = (t.f[i][j] + mu(a1.f[i][k], a2.f[k][j]) % m) % m;
46             }
47     return (t);
48 }
49 
50 data qpow(data x, long long v) {
51     data ans;
52     while (v > 0) {
53         if (v & 1) ans = ans * x;
54         x = x * x;
55         v >>= 1;
56     }
57     return (ans);
58 }
59 
60 int main () {
61     scanf("%lld %lld %lld %lld %lld %lld", &m, &a, &c, &x0, &n, &g);
62     cur.clear();
63     cur.f[1][0] = 1;
64     cur.f[1][1] = a % m;
65     cur.f[2][1] = 1;
66     cur.f[2][2] = 1;
67     cur = qpow(cur, n);
68     //cur.print();
69     long long ans = (mu(x0,cur.f[1][1]) % m + mu(c, cur.f[2][1] % m)) % m; 
70     ans = ((ans % g) + g) % g;
71     printf("%lld", ans);
72     return 0;
73 }

 

### 矩阵乘法的实现 在C++中,矩阵乘法可以通过自定义的数据结构运算符重载来实现。首先定义一个`Matrix`结构体,其中包含一个二维数组用于存储矩阵元素,并通过运算符重载实现矩阵乘法操作。矩阵乘法的时间复杂度为 $ O(n^3) $,这是由于三重循环嵌套导致的[^3]。以下是矩阵乘法的具体实现: ```cpp struct Matrix { int m[101][101]; // 假设矩阵最大为100x100 Matrix() { memset(m, 0, sizeof(m)); // 初始化矩阵为0 } }; Matrix operator*(const Matrix &x, const Matrix &y) { Matrix ret; for (int i = 1; i <= n; i++) { // n为矩阵的大小 for (int j = 1; j <= n; j++) { for (int k = 1; k <= n; k++) { ret.m[i][j] = (ret.m[i][j] + (x.m[i][k] * y.m[k][j]) % MOD) % MOD; // MOD用于,防止溢出 } } } return ret; } ``` ### 矩阵快速幂算法的实现 矩阵快速幂算法是快速幂算法在矩阵上的扩展。与普通快速幂初始化`ans`为1类似,矩阵快速幂将`ans`初始化为单位矩阵,其作用等同于1,任何矩阵乘以单位矩阵都等于原矩阵[^4]。矩阵快速幂的时间复杂度主要决于矩阵乘法的时间复杂度,即 $ O(n^3) $,但由于幂运算的对数时间复杂度,整体效率较高[^1]。以下是矩阵快速幂的具体实现: ```cpp Matrix MatrixQuickPower(const Matrix &A, int k) { Matrix res; for (int i = 1; i <= n; i++) { res.m[i][i] = 1; // 初始化res为单位矩阵 } while (k) { if (k & 1) { res = res * A; // 如果当前位为1,乘上当前的A } A = A * A; // A平方 k >>= 1; // 右移一位 } return res; } ``` ### 应用示例:斐波那契数列 矩阵快速幂的一个典型应用是求解斐波那契数列。通过构造一个转移矩阵 $ A = \begin{bmatrix} 0 & 1 \\ 1 & 1 \end{bmatrix} $,可以将斐波那契数列递推公式转化为矩阵乘法形式。初始矩阵为 $ [a_1, a_2] $,通过矩阵快速幂可以高效地计算出第 $ n $ 项[^5]。 ```cpp Matrix fibMatrix = {{0, 1}, {1, 1}}; // 构造转移矩阵 Matrix result = MatrixQuickPower(fibMatrix, n - 1); // 计算矩阵的n-1次幂 int fib_n = (result.m[1][1] * a1 + result.m[1][2] * a2) % MOD; // 计算第n项斐波那契数 ``` ### 总结 矩阵乘法矩阵快速幂是解决线性递推问题的重要工具。通过矩阵快速幂算法,可以将递推问题的时间复杂度从指数级降低到对数级,从而显著提高计算效率。在C++中,通过结构体运算符重载可以方便地实现矩阵乘法矩阵快速幂算法。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值