矩阵快速幂(warning:本体多次WA):
矩阵快速幂用途广泛,多用于递推求解,本文以肥波垃圾斐波那契数列为例
题解:
其实就是将矩阵运算套入到快速幂运算中,主要难点在于如何导出矩阵,如斐波那契数列中运算即为
{1110}n−2∗{f 2 f 1 }\left\{ \begin{matrix} 1&1\\1&0\end{matrix} \right\}^{n-2}*\left\{\begin{matrix} f~2~\\f~1~\end{matrix}\right\}{1110}n−2∗{f 2 f 1 }
其中矩阵的快速幂运算有两种方式:
WA因:结构体和单位矩阵构建有问题
1.直接写矩阵乘法函数
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long ll;
//中间运算可能会超过int范围,需要long long
const int N=2;
int n,p;
ll m;
struct node{
//结构体存储矩阵
ll g[N+2][N+2];
}f,res;
void matrixI(node &x){
//构造单位矩阵
for(int i=1; i<=N; i++){
for(int j=1; j<=N; j++)
if(i==j) x.g[i][j]=1LL;
else x.g[i][j]=0LL;
}
}
void matrixMultiple(node &x,node &y,node &z){
//矩阵乘法
memset(z.g,0,sizeof(z.g));
for(int i=1; i<=N; i++){
for(int j=1; j<=N; j++) if(x.g[i][j]){
for(int k=1; k<=N; k++){
z.g[i][k]+=x.g[i][j]*y.g[j][k];
if(z.g[i][k]>=m) z.g[i][k]%=m;
}
}
}
}
void matrixMuli(int k){
//快速幂运算
matrixI(res);
node tmp=f, t;
while(k){
if(k&1){
matrixMultiple(res,tmp,t); res=t;
}
matrixMultiple(tmp,tmp,t); tmp=t;
k>>=1;
}
}
ll solve(){
if(n<=2) return 1LL;
matrixMuli(n-2);
ll ret=res.g[1][1]+res.g[2][1];
if(ret>=m) ret-=m;
return ret;
}
int main(){
scanf("%d%d",&n,&p);
m=p;
f.g[1][1]=1;
f.g[1][2]=1;
f.g[2][1]=1;
f.g[2][2]=0;
int res=(int)solve();
printf("%d\n",res);
return 0;
}
2.重载运算符写法
不完全代码(主函数部分没写完,但矩阵乘法的重载是完整的):
#include<bits/stdc++.h>
using namespace std;
long long Mod;
struct Matrix {
long long c[101][101];
} A,I;
long long n,k;
Matrix operator*(const Matrix &x,const Matrix &y) {
Matrix a;
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
a.c[i][j]=0;
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
for(int k=1; k<=n; k++) {
a.c[i][j]+=x.c[i][k]*y.c[k][j]%Mod;
a.c[i][j]%=Mod;
}
return a;
}
int main() {
scanf("%lld%lld",&n,&Mod);
A.c[1][1]=A.c[1][2]=A.c[2][1]=1;
A.c[2][2]=0;
for(int i=1; i<=2; i++)
I.c[i][i]=1;
while(k>0) {
if(k%2==1) I=I*A;
A=A*A;
k=k>>1;
}
for(int i=1; i<=n; i++) {
for(int j=1; j<=n; j++)
cout<<I.c[i][j]<<' ';
cout<<endl;
}
return 0;
}```