题目背景
大家都知道,斐波那契数列是满足如下性质的一个数列:
f(1)=1
f(2)=1
f(n)=f(n1)+f(n2)n2n为整数)

题目描述
请你求出 f(n) mod 1000000007 的值。

输入格式
第1行:一个整数n

输出格式
第1行:f(n) mod 1000000007 的值

输入样例#1
5

输出样例#1
5

输入样例#2
10

输出样例#2
55

说明
对于 60% 的数据:n92
对于 100% 的数据:n在long long(INT64)范围内。

思路
矩阵乘法优化。(友情提示:一个n×m的矩阵A和一个m×r的矩阵相乘,得出一个n×r的矩阵,这个矩阵的ij列为mk=1,矩阵乘法不满足交换律,但满足结合律和分配律)
首先,斐波那契数列的递推式为fi=fi1+fi2,那么设有一个矩阵A

[fi1fi2]
要依据这个矩阵乘上一个矩阵trans求出另外一个矩阵B
[fifi1]
求这个矩阵trans
显然,trans这个矩阵要为
[0111]
才能满足A×trans=b
那么这样如果暴力做显然是O(n)的,并没有优化。
考虑到
[f2f1]×[0111]n2=[fnfn1]
并且矩阵乘法满足结合律,那么可以用快速幂优化。
最终时间复杂度O(logn)

代码

#include <cstdio>

const int maxn=10;
const int mo=1000000007;

struct matrix
{
  long long a[maxn+1][maxn+1],r,c;

  matrix operator *(const matrix &other)
  {
    matrix res;
    res.r=r;
    res.c=other.c;
    for(int i=1; i<=res.r; i++)
      {
    for(int j=1; j<=res.c; j++)
      {
        long long sum=0;
        for(int k=1; k<=c; k++)
          {
        sum+=a[i][k]*other.a[k][j];
        sum%=mo;
          }
        res.a[i][j]=sum;
      }
      }
    return res;
  }
};

long long n;
matrix t,c,ans;

matrix quickpow(matrix a,long long b,int m)
{
  matrix res;
  res.c=a.c;
  res.r=a.r;
  for(int i=1; i<=res.r; i++)
    {
      for(int j=1; j<=res.c; j++)
    {
      res.a[i][j]=0;
    }
      res.a[i][i]=1;
    }
  while(b)
    {
      if(b&1)
    {
      res=res*a;
      b--;
    }
      b/=2;
      a=a*a;
    }
  return res;
}

inline long long read()
{
  long long x=0;
  int f=1;
  char ch=getchar();
  while((ch<'0')||(ch>'9'))
    {
      if(ch=='-')
    {
      f=-f;
    }
      ch=getchar();
    }
  while((ch>='0')&&(ch<='9'))
    {
      x=x*10+ch-'0';
      ch=getchar();
    }
  return x*f;
}

int main()
{
  n=read();
  if(n==1ll)
    {
      printf("1\n");
      return 0;
    }
  t.r=1;
  t.c=2;
  t.a[1][1]=1;
  t.a[1][2]=1;
  c.r=2;
  c.c=2;
  c.a[1][1]=0;
  c.a[1][2]=1;
  c.a[2][1]=1;
  c.a[2][2]=1;
  ans=t*quickpow(c,n-2,mo);
  printf("%lld\n",ans.a[1][2]);
  return 0;
}