题解——洛谷P1962 斐波那契数列(矩阵乘法)

矩阵乘法加速线性递推的典型

大概套路就是先构造一个矩阵\( F \)使得另一初始矩阵\( A \)乘以\( F^{x} \)能够得出第n项

跑的飞快

虽然我也不知道那个矩阵要怎么构造

或许就像我使用了瞪眼法和枚举法

#include <cstdio>
#include <algorithm>
#include <cstring>
#define int long long
using namespace std;
const int MOD = 1000000007;
int n;
struct Matrix{
  static const int MAXN = 100;
  int alpha[MAXN][MAXN];
  int n,m;
  void init(void){
    for(int i=0;i<MAXN;i++)
      for(int j=0;j<MAXN;j++)
        alpha[i][j]=0;
    n=m=0;
  }
  void init_f2(void){
    n=2;m=2;
    alpha[1][1]=1;
    alpha[2][1]=1;
    alpha[1][2]=1;
    alpha[2][2]=0;
  }
  void init_f(void){
    n=1;m=2;
    alpha[1][1]=1;
    alpha[1][2]=1;
  }
  void init_pow(int x){
    for(int i=1;i<=x;i++)
      alpha[i][i]=1;
    m=n=x;
  }
  Matrix operator * (Matrix b){
    Matrix c;
    c.init();
    for(int i=1;i<=n;i++)
      for(int j=1;j<=b.m;j++)
        for(int k=1;k<=m;k++)
          c.alpha[i][j]=(c.alpha[i][j]%MOD+alpha[i][k]*b.alpha[k][j]%MOD)%MOD;
    c.n=n;
    c.m=b.m;
    return c;
  }
};
Matrix pow(Matrix a,int p){
  Matrix ans;
  ans.init();
  ans.init_pow(a.n);
  while(p){
    if(p&1)
      ans=ans*a;
    a=a*a;
    p>>=1;
  }
  return ans;
}
signed main(){
  scanf("%lld",&n);
  Matrix f,f2,ans;
  f.init();
  f.init_f();
  f2.init();
  f2.init_f2();
  ans=pow(f2,n-1);
//  for(int i=1;i<=ans.n;i++){
//    for(int j=1;j<=ans.m;j++)
//      printf("%d ",ans.alpha[i][j]);
//    printf("\n");
//    }
  f=f*ans;
  printf("%lld",f.alpha[1][2]%MOD);
  return 0;
}

 

posted @ 2018-09-07 17:30  dreagonm  阅读(257)  评论(0编辑  收藏  举报