这题比较综合,我参考了一下大佬的代码,想自己整理总结记录一下。
附上参考链接:https://blog.youkuaiyun.com/weixin_43578474/article/details/105666514
题目详情
题解
快速矩阵幂与斐波那契相结合,关系如下:
以[f(1), f(0)]为基准,f(1) = 1, f(0) = 0,所以矩阵幂得出的结果矩阵,只要第一项乘以f(1),即为其本身即可。
重要思想
-
普通快速幂代码,求a^n(二分法)
int res = 1; while(n > 0) { if(n % 2) res *= a; a = a * a; n /= 2; }
-
矩阵快速幂
矩阵快速幂,res就变为了单位矩阵,a则为要乘的矩阵,此时就需要考虑矩阵的定义和如何实现矩阵乘法
-
矩阵结构体定义
typedef struct Matrix { unsigned long long M[2][2]; }Matrix;
-
矩阵乘法
一般情况:
若A为n×t矩阵,B为t×m矩阵,则它们的乘积C将是一个n×m矩阵。两个矩阵能相乘的前提条件为前一个矩阵的列数等于后一个矩阵的行数。
for(int i = 0; i < n; i++) { for(int j = 0; j < m; j++) { c[i][j] = 0; for(int k = 0; k < t; k++) c[i][j] += a[i][k]*b[k][j]; } }
本题矩阵相乘函数:
struct Matrix multi(Matrix a, Matrix b) { Matrix c; for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { c.M[i][j] = 0; for (int k = 0; k < 2; k++) c.M[i][j] += (a.M[i][k] * b.M[k][j])%mod; } } return c; }
-
矩阵快速幂代码
struct Matrix QuickExp(Matrix a, unsigned long long n) { Matrix res; res.M[0][0] = 1; //单位矩阵 res.M[0][1] = 0; res.M[1][0] = 0; res.M[1][1] = 1; while (n > 0) { if (n % 2) res = multi(res, a); a = multi(a, a); n /= 2; } return res; }
-
完整代码
#include<stdio.h>
#define mod 998244353
typedef struct Matrix
{
unsigned long long M[2][2];
}Matrix;
struct Matrix multi(Matrix a, Matrix b)
{
Matrix c;
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
c.M[i][j] = 0;
for (int k = 0; k < 2; k++)
c.M[i][j] += (a.M[i][k] * b.M[k][j])%mod;
}
}
return c;
}
struct Matrix QuickExp(Matrix a, unsigned long long n)
{
Matrix res;
res.M[0][0] = 1; //单位矩阵
res.M[0][1] = 0;
res.M[1][0] = 0;
res.M[1][1] = 1;
while (n > 0)
{
if (n % 2)
res = multi(res, a);
a = multi(a, a);
n /= 2;
}
return res;
}
int main()
{
unsigned long long n;
Matrix a, res;
scanf("%lld", &n);
if(n == 1)
{
printf("1\n");
return 0;
}
a.M[0][0] = 1;a.M[0][1] = 1;
a.M[1][0] = 1;a.M[1][1] = 0;
res = QuickExp(a, n - 1);
printf("%lld\n",res.M[0][0]%mod); //以[f(1),f(0)]为基准
return 0;
}