zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    MSSQL经典语句
    注销时关闭当前窗体,返回登入界面
    自定义控件小结进阶篇
    精妙SQL语句大全
    触发器MSSQL常用操作
    经典SQL语句大全
    文件下载
    android Notification 的使用
    startActivityForResult()的用法
    Android手机中获取手机号码和运营商信息
  • 原文地址:https://www.cnblogs.com/nancheng58/p/10067999.html
Copyright © 2011-2022 走看看