Cogs 1708. 斐波那契平方和(矩阵乘法)

  1. 斐波那契平方和
    ★★☆ 输入文件:fibsqr.in 输出文件:fibsqr.out 简单对比
    时间限制:0.5 s 内存限制:128 MB
    【题目描述】
    这里写图片描述,对 1000000007 取模。F0=0,F1=1,F2=1
    【输入格式】
    一行一个整数 N
    【输出格式】
    一行一个整数 Ans
    【样例输入】
    4
    【样例输出】
    15
    【数据范围】
    1≤ N ≤1015
/*
矩阵乘法.
     n
定理:∑f[i]^2=f[n]*f[n+1]. 
    i=1
Codevs3969的n<=10^50000直接弃疗了.
(20W遍快速幂 字符串处理是O(L)的然后就T了。。。
这个定理证明的话就是网上那个著名的
与斐波那契相关的图.
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#define mod 1000000007
#define LL long long
using namespace std;
char ch[50010];
int n[50010];
LL ans[3][3],b[3][3],c[3][3],tot,l;
bool check()
{
    for(int i=1;i<=l;i++) if(n[i]) return true;
    return false;
}
void Div()
{
    for(int i=l;i>=1;i--)
      {
        n[i-1]+=10*(n[i]%2);
        n[i]/=2;
      }
    while(!n[l]) l--;
}
void mi()
{
    while(check())
    {
        if(n[1]&1)
        {
            for(int i=1;i<=2;i++)
              for(int j=1;j<=2;j++)
                for(int k=1;k<=2;k++)
                  c[i][j]=(c[i][j]+ans[i][k]*b[k][j]%mod)%mod;
            for(int i=1;i<=2;i++)
              for(int j=1;j<=2;j++)
                ans[i][j]=c[i][j],c[i][j]=0;
        }
        for(int i=1;i<=2;i++)
          for(int j=1;j<=2;j++)
            for(int k=1;k<=2;k++)
              c[i][j]=(c[i][j]+b[i][k]*b[k][j]%mod)%mod;
        for(int i=1;i<=2;i++)
          for(int j=1;j<=2;j++)
            b[i][j]=c[i][j],c[i][j]=0;
        Div();
    }
}
void slove()
{
    ans[1][1]=1,ans[1][2]=0;
    b[1][1]=b[1][2]=b[2][1]=1;
    mi();
    tot=(ans[1][1]%mod*ans[1][2]%mod)%mod;
}
int main()
{
    freopen("fibsqr.in","r",stdin);
    freopen("fibsqr.out","w",stdout);
    cin>>ch+1;l=strlen(ch+1);
    for(int i=1;i<=l;i++) n[i]=ch[l-i+1]-48;
    slove();
    cout<<tot;
    return 0;
}
posted @ 2017-03-23 20:26  nancheng58  阅读(251)  评论(0编辑  收藏  举报