11/25总结
矩阵乘法
核心:
- 对于A*B=C
- A为n*m的矩阵,B为m*p的矩阵,则C为n*p的矩阵
- (对于矩阵中每一个小格)C[ i ][ j ]=A的第i行旋转90°*B的第j列每个数分别相乘再相加
- 满足结合律,分配律,不满足交换律
- 基本形式:初始状态矩阵*转移矩阵的n次方
- 转移矩阵设计:若状态矩阵中的第x个数对下一状态矩阵中的第y个数产生影响,则将转移矩阵的第x行第y列进行赋值
- 使用条件:线性递推加速,降低为o(n^3logT),T为递推总轮数
代码:
struct matrix
{
long long f[105][105];
} A,ans;//若matrix边长不确定存r,c;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.f[ 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.f[i][j]=(a.f[i][j]+x.f[i][k]*y.f[k][j]%mod);
{
a.f[i][j]+=x.f[i][k]*y.f[k][j]%mod;
a.f[i][j]%=mod;
}
return a;
}
for(int i=1;i<=n;i++)
ans.f[i][i]=1;//单位矩阵
while(k>0)
{
if(k&1)
ans=ans*A;
A=A*A;
k>>=1;
}// for(int i=0;i<=0;i++);
for(int j=0;j<=1;j++)
for(int k=0;k<=1;k++)
{
c[j]+=d[k]*ans.f[k][j]%m;//最后初始乘上状态矩阵
// cout<<j<<" "<<k<<" "<<d[k]<<"*"<<ans.f[k][j]<<" "<<c[j]<<endl;
c[j]%=m;
}
注意事项:
- 进行矩阵乘时需要另开结构体或数组存答案(斐波那契数列的数据太水了最后乘状态矩阵没开新数组存就过了,导致做另一道题的时候一直没检查出错误)
- 注意转移状态需要自幂的次数,初始是从第0项还是第1项,是否需要特判询问初始状态的情况
update 12.23