标签:矩阵乘法 typedef 要求 space 初始 重载运算符 ++ src out
#include <iostream> using namespace std; const int mod = 1000000007; typedef long long ll; int main() { ll n; cin >> n; ll a = 1; ll b = 1; ll ans = 1; for (int i = 2; i <= n; i++) { int temp = a; a = (a % mod + b % mod) % mod; b = temp; } cout << a << endl; return 0; }
// 超时代码
这里我们先引入复习一下快速幂模板
#include <iostream> using namespace std; typedef long long ll; ll mul(ll a, ll b, ll p) { ll ans = 1; while (b) { if (b & 1) ans = ans * a % p; a = a * a % p; b >>= 1; } return ans ; } int main() { ll a, b, p; cin >> a >> b >> p; cout << mul(a, b, p) << endl; return 0; }
这里贴上新学习的矩阵快速幂的模板
个人认为比较好理解一些
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; typedef long long ll; const int N = 105, mod = 1000000007; int n; ll k; struct Mat { ll a[N][N]; // longlong存矩阵 否则过程中会爆掉 Mat() { memset(a, 0, sizeof a); } inline void build() //建造单位矩阵 { for (int i = 1; i <= n; i ++ ) a[i][i] = 1; } }mat; Mat operator * (const Mat &x, const Mat &y) //重载运算符 { Mat z; for (int k = 1; k <= n; k ++ ) for (int i = 1; i <= n; i ++ ) for (int j = 1; j <= n; j ++ ) z.a[i][j] = (z.a[i][j] + x.a[i][k] * y.a[k][j] % mod) % mod; return z; } int main() { cin >> n >> k; for (int i = 1; i <= n; i ++) for (int j = 1; j <= n; j ++ ) cin >> mat.a[i][j]; Mat ans; ans.build(); // 实际相当于求快速幂中ans=1 这里ans为矩阵 所以初始化为单位矩阵 while (k) { if (k & 1) ans = ans * mat; mat = mat * mat; k >>= 1; } for (int i = 1; i <= n; i ++ ) { for (int j = 1; j <= n; j ++ ) cout << ans.a[i][j] << ‘ ‘; cout << endl; } return 0; }
在求斐波那契数列 可以使用矩阵快速幂
矩阵快速幂是用来求解递推式的,所以第一步先要列出递推式:
f(n)=f(n-1)+f(n-2)
第二步是建立矩阵递推式,找到转移矩阵:
,简写成T * A(n-1)=A(n),T矩阵就是那个2*2的常数矩阵,而
这里就是个矩阵乘法等式左边:1*f(n-1)+1*f(n-2)=f(n);1*f(n-1)+0*f(n-2)=f(n-1);
所以这里相乘就是矩阵n-1次相乘,然后输出第一行第二个元素,也就是a[0][1];
把第一个矩阵设为A,第二个矩阵设为B,第三个矩阵设为C。
总而言之 :最终斐波那契数列可以从矩阵中对应此公式
由 F2 F1 F1 F0 组成的矩阵的n次方 的左下角就是Fn。
所以可以上代码
注:此题和标准的斐波那契数列(1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, ...)有不同处
标准的即f0=0,f1=1,f2=1,f3=2 而此题中f1=1,f2=2
所以我们最后实则应该求f的n+1项
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; typedef long long ll; const int mod = 1000000007; ll n, k; struct Mat { ll a[2][2]; Mat() { memset(a, 0, sizeof a); } inline void build() { for (int i = 0; i < 2; i ++ ) a[i][i] = 1; } }base; Mat operator * (const Mat &x, const Mat &y) { Mat z; for (int k = 0; k < 2; k ++ ) for (int i = 0; i < 2; i ++ ) for (int j = 0; j < 2; j ++) z.a[i][j] = (z.a[i][j] + x.a[i][k] * y.a[k][j] % mod) % mod; return z; } int main() { cin >> n; base.a[0][0] = 1, base.a[0][1] = 1, base.a[1][0] = 1, base.a[1][1] = 0; //将base初始化为要求n次幂的矩阵 Mat ans; ans.build(); while (n) { if (n & 1) ans = ans * base; base = base * base; n >>= 1; } cout << ans.a[0][0] << endl; // cout << ans.a[1][0] << endl; 注意这一道题的f1=1 f2=2 和标准的斐波那契数列有一定区别 return 0; }
标签:矩阵乘法 typedef 要求 space 初始 重载运算符 ++ src out
原文地址:https://www.cnblogs.com/zbx2000/p/12735111.html