一、矩阵乘法
矩阵A*B=C,公式: ,三重循环。
前提条件:n*n的矩阵
看代码:
const int N=100;
int c[N][N];
void multi(int a[][N],int b[][N],int n)//n是矩阵大小,n<N
{
memset(c,0,sizeof c);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++)
c[i][j]+=a[i][k]*b[k][j];
}
二、矩阵快速幂
2.1. 整数快速幂
例子:
19=1 0011
- ans = res*ans = x; res = res*res = x^2;
- ans = res*ans = x*(x^2) = x^3; res = res*res = x^2*x^2 = x^4
- res = res*res = x^4*x^4 = x^8
- res = res*res =x^8*x^8= x^16
- ans = ans*res = (x^3)*(x^16)= x^19; res = res*res = x^32
res指数级增长,代表指数N每一位增长的次数,得到粗略结果,ans则将前一位的次数*该位的权值,得到精确结果。
int QuickPow(int x,int N)
{
int res = x;
int ans = 1;
while(N)
{
if(N&1)
{
ans = ans * res;
}
res = res*res;
N = N>>1;
}
return ans;
}
2.2. 矩阵快速幂
类比一下,大同小异。
const int N=10;
int tmp[N][N];
//tmp=A*B,再把tmp赋给A,就是A^2
void multi(int a[][N],int b[][N],int n)
{
memset(tmp,0,sizeof tmp);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
for(int k=0;k<n;k++)
tmp[i][j]+=a[i][k]*b[k][j];
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
a[i][j]=tmp[i][j];
}
int ans[N][N];
void Pow(int res[][N],int n)
{
//首先初始化
memset(ans,0,sizeof ans);//n是幂,N是矩阵大小
for(int i=0;i<N;i++) ans[i][i]=1;
//
while(n)
{
if(n&1)
multi(ans,res,N);//ans=ans*res;复制直接在multi里面实现了;
multi(res,res,N);//res=res*res
n>>=1;
}
}
三、应用
用于线性DP的递推式:
举几个例子:
1.f(n)=af(n-1)+bf(n-2)+c;(a,b,c是常数),
2.f(n)=c^n-f(n-1) ;(c是常数),
3.f(n)=a*f(n-1)+c^n
,
进行矩阵快速幂就好啦!
csp 202006-4 1246可以应用这个算法,过几天编了更。