[浅谈·矩阵快速幂]
矩阵快速幂
•矩阵快速幂实质上将矩阵作为一个整体,用快速幂的思想进行运算
•但要注意三点:
•1.十年OI一场空,不开long long见祖宗
•2.注意矩阵乘法的顺序,不满足交换律
•3.基础矩阵作为快速幂中的 ” 1 ”
矩阵快速幂的实际应用有很多种,其中最主要的是矩阵加速数列
回到P1932 如何用矩阵实现加速
设矩阵
| f(n) | 它可以表示为 | f(n-1)+f(n-2) |
| f(n-1) | (Maxtrix A) | f(n-1) |(Maxtrix C)
可以考虑设一个矩阵 B 使得 B*A=C(顺序性) (A*B和B*A不同!!!)
•根据矩阵相乘的原理,容易得出这个矩阵为
•| 1 0 |
•| 1 1 |
•因此如果要让f(1) 变成 f(n) ,只需要重复地乘 n 次B矩阵,再取
•矩阵中(1,1)的值即可
•
•F(n)=f(1)*B^n
P3390code
#include<iostream>
#include<cstdio>
#define ll long long
#define mod 1000000007
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
int n;
ll k;
struct Maxtrix{
ll m[205][205];
}ans,res,IOI;
Maxtrix Mul(Maxtrix A,Maxtrix B)
{
Maxtrix temp;
memset(temp.m,0,sizeof(temp.m));
for(register int i=1;i<=n;i++)
for(register int j=1;j<=n;j++)
for(register int k=1;k<=n;k++)
temp.m[i][j]=(temp.m[i][j]%mod+(A.m[i][k]%mod*B.m[k][j])%mod)%mod;
return temp;
}
Maxtrix quickPower(Maxtrix a,ll N)
{
Maxtrix ans;
for(register int i=1;i<=n;i++) ans.m[i][i]=1;
while(N)
{
if(N&1)
ans=Mul(ans,a);
a=Mul(a,a);
N>>=1;
}
return ans;
}
int main()
{
cin>>n>>k;
for(register int i=1;i<=n;i++)
for(register int j=1;j<=n;j++){
cin>>res.m[i][j];
}
IOI=quickPower(res,k);
for(register int i=1;i<=n;i++)
{
for(register int j=1;j<=n;j++)
{
printf("%lld ",IOI.m[i][j]%mod);
}
printf("\n");
}
return 0;
}
#include<cstdio>
#define ll long long
#define mod 1000000007
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
int n;
ll k;
struct Maxtrix{
ll m[205][205];
}ans,res,IOI;
Maxtrix Mul(Maxtrix A,Maxtrix B)
{
Maxtrix temp;
memset(temp.m,0,sizeof(temp.m));
for(register int i=1;i<=n;i++)
for(register int j=1;j<=n;j++)
for(register int k=1;k<=n;k++)
temp.m[i][j]=(temp.m[i][j]%mod+(A.m[i][k]%mod*B.m[k][j])%mod)%mod;
return temp;
}
Maxtrix quickPower(Maxtrix a,ll N)
{
Maxtrix ans;
for(register int i=1;i<=n;i++) ans.m[i][i]=1;
while(N)
{
if(N&1)
ans=Mul(ans,a);
a=Mul(a,a);
N>>=1;
}
return ans;
}
int main()
{
cin>>n>>k;
for(register int i=1;i<=n;i++)
for(register int j=1;j<=n;j++){
cin>>res.m[i][j];
}
IOI=quickPower(res,k);
for(register int i=1;i<=n;i++)
{
for(register int j=1;j<=n;j++)
{
printf("%lld ",IOI.m[i][j]%mod);
}
printf("\n");
}
return 0;
}