矩阵乘法
矩阵乘法入门
矩阵
类似一个二维数组吧。
矩阵的运算
矩阵的加法
我不知道有什么用。
矩阵的减法
我也不知道有什么用。
矩阵的乘法
即答案矩阵的第
矩阵乘法代码
struct matrix {
long long num[3][3];
void init() {
memset(num, 0, sizeof(num));
}
matrix operator * (const matrix& x) const {
matrix res;
res.init();
for (int i = 1; i <= 2; i ++)
for (int j = 1; j <= 2; j ++)
for (int k = 1; k <= 2; k ++)
res.num[i][j] += num[i][k] * x.num[k][j]
return res;
}
};
题目
1. 斐波那契数列
大家都知道,斐波那契数列是满足如下性质的一个数列:
请你求出
【数据范围】
对于
对于
思路
斐波那契数列的递推式很简单,为
对于
对于
求出
我们还需要构造一个矩阵
可以看出来,
这样就很好理解了,
求出了
为什么是
乘
所以:
因为
矩阵快速幂和数的快速幂非常相似,唯一不同的地方就是
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1000000007;
struct matrix {
LL a[4][4];
matrix() {memset(a, 0, sizeof(a));}
matrix operator * (const matrix& x) const {
matrix res;
for (int i = 1; i <= 3; i ++)
for (int j = 1; j <= 3; j ++)
for (int k = 1; k <= 3; k ++) {
res.a[i][j] = (res.a[i][j] + (a[i][k] % mod * x.a[k][j] % mod) % mod) % mod;
}
return res;
}
matrix operator ^ (LL p) const {
matrix res, x;
for (int i = 1; i <= 3; i ++) res.a[i][i] = 1;
for (int i = 1; i <= 3; i ++)
for (int j = 1; j <= 3; j ++)
x.a[i][j] = a[i][j];
while (p) {
if (p & 1) res = res * x;
x = x * x;
p >>= 1;
}
return res;
}
};
matrix m, p;
int main() {
LL n;
scanf("%lld", &n);
if (n <= 2) {
puts("1");
return 0;
}
p.a[1][1] = p.a[1][2] = p.a[2][1] = 1;
m.a[1][1] = m.a[1][2] = 1;
m = m * (p ^ (n - 2));
printf("%lld\n", m.a[1][1]);
return 0;
}
2. Fibonacci 前 n 项和
大家都知道
现在问题很简单,输入
思路
这道题就比上道题升级了,需要求前
还是构造一个矩阵:
与上一题同理,我们需要构造出一个矩阵
为了更直观的表现,我们在矩阵旁边标上对应的数太麻烦了,不标了。可以很简单的构造出:
剩下的
遇上一题一样,还是快速幂,不过这一次是
初始矩阵:
代码
#include <bits/stdc++.h>
using namespace std;
long long n, m;
struct matrix {
long long num[4][4];
void init() {
memset(num, 0, sizeof(num));
}
matrix operator * (const matrix& x) const {
matrix res;
res.init();
for (int i = 1; i <= 3; i ++)
for (int j = 1; j <= 3; j ++)
for (int k = 1; k <= 3; k ++)
res.num[i][j] = (res.num[i][j] + (num[i][k] % m * x.num[k][j] % m) % m) % m;
return res;
}
matrix operator ^ (long long p) const {
matrix res, a;
res.init();
for (int i = 1; i <= 3; i ++)
res.num[i][i] = 1;
for (int i = 1; i <= 3; i ++)
for (int j = 1; j <= 3; j ++)
a.num[i][j] = num[i][j];
while (p) {
if (p & 1) res = res * a;
a = a * a;
p >>= 1;
}
return res;
}
};
matrix a, b;
int main() {
scanf("%lld%lld", &n, &m);
a.num[1][1] = a.num[1][2] = a.num[1][3] = 1;
b.num[1][1] = b.num[2][1] = b.num[2][2] = b.num[2][3] = b.num[3][2] = 1;
a = a * (b ^ (n - 1));
printf("%lld\n", a.num[1][1]);
return 0;
}
3. fib
思路
这道题就更加升级了,增加了一些系数和常数,我们把这些全部放入矩阵。
这样我们的矩阵
剩下的就是常规的快速幂,
代码
#include <bits/stdc++.h>
using namespace std;
long long m = 10000;
struct matrix {
long long num[6][6];
void init() {
memset(num, 0, sizeof(num));
}
matrix operator * (const matrix& x) const {
matrix res;
res.init();
for (int i = 1; i <= 5; i ++)
for (int j = 1; j <= 5; j ++)
for (int k = 1; k <= 5; k ++)
res.num[i][j] = (res.num[i][j] + (num[i][k] % m * x.num[k][j] % m) % m) % m;
return res;
}
matrix operator ^ (long long p) const {
matrix res, a;
res.init();
for (int i = 1; i <= 5; i ++)
res.num[i][i] = 1;
for (int i = 1; i <= 5; i ++)
for (int j = 1; j <= 5; j ++)
a.num[i][j] = num[i][j];
while (p) {
if (p & 1) res = res * a;
a = a * a;
p >>= 1;
}
return res;
}
};
matrix a, b;
long long n;
int main() {
while (scanf("%lld", &n) != EOF) {
if (n == -1) break;
if (n <= 2) {
puts("0");
continue;
}
a.num[1][1] = 0,
a.num[1][2] = 0,
a.num[1][3] = 10,
a.num[1][4] = 5,
a.num[1][5] = 9,
b.num[1][1] = 7,
b.num[2][1] = 6,
b.num[3][1] = 1,
b.num[4][1] = 1,
b.num[5][1] = 12,
b.num[1][2] = 1,
b.num[3][3] = 1;
b.num[4][3] = 1,
b.num[4][4] = 1,
b.num[5][5] = 3;
a = a * (b ^ (n - 2));
printf("%lld\n", a.num[1][1]);
}
return 0;
}
总结
构造矩阵时要把递推式中所有项都塞到矩阵里。
矩阵的
转眼5个月没写博客了,今天开始继续写。
本文来自博客园,作者:maniubi,转载请注明原文链接:https://www.cnblogs.com/maniubi/p/17550177.html,orz
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】