11/25总结

矩阵乘法

核心:

  • 对于A*B=C
  1. A为n*m的矩阵,B为m*p的矩阵,则C为n*p的矩阵
  2. (对于矩阵中每一个小格)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;
  }

注意事项:

  1. 进行矩阵乘时需要另开结构体或数组存答案(斐波那契数列的数据太水了最后乘状态矩阵没开新数组存就过了,导致做另一道题的时候一直没检查出错误)
  2. 注意转移状态需要自幂的次数,初始是从第0项还是第1项,是否需要特判询问初始状态的情况

 

 

update 12.23

 

posted @ 2023-11-25 17:37  某不知名碳基生物  阅读(16)  评论(0)    收藏  举报