矩阵乘法
1 2 3 4 5 6 7 8 9 10 11
| A = a*b B = b*c A x B = a*c for(int i=1;i<=a;i++){ for(int j=1;j<=c;j++){ for(int k=1;k<=b;k++){ C[i][j]+=A[i][k]*B[k][j]; } } }
|
矩阵快速幂 求斐波那契
题意
求斐波那契第i项
思路
利用矩阵运算的性质将通项公式变成幂次形式,然后用平方倍增(快速幂)的方法求解第 n 项。
首先我们定义向量
然后我们可以找出矩阵:
则有:
所以:
由于矩阵具有结合律, 所以我们可以先求出 $A^{n-1} \% P$, 然后再用 $X_{1}$ 左乘, 即可求出 $X_{n}$, 向量 $X_{n}$ 的第一 个元素就是 $a_{n}$ 。
题意
思路

代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| #include <cstring> #include <iostream> #include <algorithm>
using namespace std;
typedef long long LL; LL A[3][3]={1,1,1, 1,0,0, 0,0,1}; LL B[3][3]={1,0,0, 0,1,0, 0,0,1}; LL n,m; LL F[3]={1,1,1};
void mul(LL a[3][3],LL b[3][3]){ LL temp[3][3]; memset(temp,0,sizeof temp); for(int i=0;i<3;i++){ for(int j=0;j<3;j++){ for(int k=0;k<3;k++){ temp[i][j]=(temp[i][j]+a[i][k]*b[k][j])%m; } } } for(int i=0;i<3;i++) for(int j=0;j<3;j++) a[i][j] = temp[i][j]; }
int main() { cin>>n>>m; n--; while(n){ if(n&1) mul(B,A); mul(A,A); n>>=1; } cout<<(B[0][2]+B[1][2]+B[2][2])%m; return 0; }
|
总结
先列出 Fi 和 Fi-1 再直接写出A。有点动态规划的意思。
题意
用 $T(n)=\left(F_{1}+2 F_{2}+3 F_{3}+\ldots+n F_{n}\right) \bmod m$ 表示 Fibonacci 数列前 $n$ 项变形后的和 $\bmod m$ 的值。 现在佳佳告诉你了一个 $n$ 和 $m$, 请求出 $T(n)$ 的值。
思路
A矩阵中不能有变量,所以不能直接做
曲线救国的方法

代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| #include <cstring> #include <iostream> #include <algorithm>
using namespace std;
typedef long long LL;
const int N = 4;
int n, m;
void mul(int c[][N], int a[][N], int b[][N]) { static int t[N][N]; memset(t, 0, sizeof t);
for (int i = 0; i < N; i ++ ) for (int j = 0; j < N; j ++ ) for (int k = 0; k < N; k ++ ) t[i][j] = (t[i][j] + (LL)a[i][k] * b[k][j]) % m;
memcpy(c, t, sizeof t); }
int main() { cin >> n >> m;
int f1[N][N] = {1, 1, 1, 0}; int a[N][N] = { {0, 1, 0, 0}, {1, 1, 1, 0}, {0, 0, 1, 1}, {0, 0, 0, 1}, };
int k = n - 1;
while (k) { if (k & 1) mul(f1, f1, a); mul(a, a, a); k >>= 1; }
cout << (((LL)n * f1[0][2] - f1[0][3]) % m + m) % m << endl;
return 0; }
|
总结
可以把向量扩充为矩阵,就不用多写代码了