矩阵快速幂、矩阵加速递推
写数论文章写爽了。
矩阵快速幂
矩阵乘法
矩阵乘法要求
设
矩阵乘法必须第一个矩阵的列数等于第二个矩阵的行数。
我们一起计算一下:
即:
矩阵的幂运算
计算
- 先算二次幂:
\begin{bmatrix}1 & 2\\2 & 1\end{bmatrix}^2=\begin{bmatrix}1 & 2\\2 & 1\end{bmatrix}\times\begin{bmatrix}1 & 2\\2 & 1\end{bmatrix}=\begin{bmatrix}5 & 4\\4 & 5\end{bmatrix} - 再算三次幂:
\begin{bmatrix}5 & 4\\4 & 5\end{bmatrix}\times\begin{bmatrix}1 & 2\\2 & 1\end{bmatrix}=\begin{bmatrix}13 & 14\\14 & 13\end{bmatrix} 单位矩阵
单位矩阵
I=\begin{bmatrix}1 & 0\\0 & 1\end{bmatrix} ,与任意矩阵相乘不改变其值。
一个
矩阵快速幂的实现
比较简单,建立一个矩阵结构体封装即可。
class matrix{
public:
matrix()
:n(0)
{
memset(c, 0, sizeof(c));
}
int* operator[](int t)
{
return c[t];
}
void init()//建立单位矩阵
{
for(int i = 1; i <= n; i++)
c[i][i] = 1;
}
int size()
{
return n;
}
private:
int c[110][110];
int n;
};
matrix operator*(matrix x, matrix y)//矩阵乘法
{
matrix ans;
int n = x.size();
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
for(int k = 1; k <= n; k++)
ans[i][j] += x[i][k] * y[k][j];
}
matrix quick_pow(matrix x, int y)//矩阵快速幂
{
matrix ans;
ans.init();//注意这里需要是单位矩阵
while(y)
{
if(y & 1) ans = ans * x;
y >>= 1;
x = x * x;
}
return ans;
}
时间复杂度为:
矩阵加速递推
求斐波那契数列(P1962 斐波那契数列):
思路
构造矩阵
我们把斐波那契数列的相邻两项表示为一个矩阵
构造转移矩阵
我们构造一个矩阵
根据递推关系:
观察可得:
递推
我们发现:
时间复杂度
矩阵快速幂为
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 1e9 + 7;
int n = 2;
struct matrix{
int c[3][3];
matrix()
{
memset(c, 0, sizeof(c));
}
void init()
{
for(int i = 1; i <= n; i++)
c[i][i] = 1;
}
};
matrix operator*(matrix x, matrix y)
{
matrix ans;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
for(int k = 1; k <= n; k++)
ans.c[i][j] = (ans.c[i][j] + x.c[i][k] * y.c[k][j]) % mod;
return ans;
}
matrix quick_pow(matrix x, int y)
{
matrix ans;
ans.init();
while(y)
{
if(y & 1) ans = ans * x;
y >>= 1;
x = x * x;
}
return ans;
}
signed main()
{
int m;
cin >> m;
if(m <= 2) cout << 1, exit(0);
matrix a;
a.c[1][1] = a.c[1][2] = 1;
matrix b;
b.c[1][1] = b.c[1][2] = b.c[2][1] = 1;
b = quick_pow(b, m - 2);
matrix ans = a * b;
cout << ans.c[1][1];
return 0;
}
作业
已知一个函数为:
给出
还有,欢迎来到我的博客玩哦!