zoukankan      html  css  js  c++  java
  • 【洛谷1962】 斐波那契数列

    题面

    题目背景

    大家都知道,斐波那契数列是满足如下性质的一个数列:

    • f(1) = 1

    • f(2) = 1

    • f(n) = f(n-1) + f(n-2) (n ≥ 2 且 n 为整数)

    题目描述

    请你求出 f(n) mod 1000000007 的值。

    输入格式:

    ·第 1 行:一个整数 n

    输出格式:

    第 1 行: f(n) mod 1000000007 的值

    输入输出样例

    输入样例#1:

    5

    输出样例#1:

    5

    输入样例#2:

    10

    输出样例#2:

    55

    说明

    对于 60% 的数据: n ≤ 92

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

    题解

    看一看数据范围
    如果使用O(n)的递推显然会炸掉
    那么我们有没有别的方法?

    显然是有的
    使用斐波那契数列的递推公式怎么样?
    但是,,,里面带有根号,如果直接使用显然是会掉精度的

    所以,,,应该怎么办

    我们知道
    f[i]=f[i-1]+f[i-2]
    f[i-1]=f[i-2]+f[i-3]

    所以
    我们可以用矩阵来表示
    这里写图片描述
    因此
    我们可以继续推导
    可以得到

    这里写图片描述

    接下来使用矩阵快速幂就可以直接求解

    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    #define MOD 1000000007
    #define MAX 10
    #define ll long long
    struct yl//矩阵 
    {
    	   int n;//大小
    	   long long g[MAX][MAX];  
    };
    yl operator *(yl a,yl b)//定义乘法 
    {
    	   int n=a.n;
    	   yl cool;
    	   memset(cool.g,0,sizeof(cool.g));
    	   for(int i=1;i<=n;++i)
    	   	    for(int j=1;j<=n;++j)
    				 for(int k=1;k<=n;++k)
    				        cool.g[i][j]=(cool.g[i][j]+1ll*a.g[i][k]*b.g[k][j]%MOD)%MOD;
    	   cool.n=n;
    	   return cool;
    }
    void write(yl a)
    {
    	   int n=a.n;
    	   for(int i=1;i<=n;++i)
    	   {
    	       for(int j=1;j<=n;++j)
    		      cout<<a.g[i][j]<<' ';
    		   cout<<endl;
    	   }
    }
    yl Pow(yl a,long long b)//a的b次方
    {
    	   if(b==1)return a;
    	   yl s=Pow(a,b/2);
    	   s.n=a.n;
    	   s=s*s;
    	   if(b&1)s=s*a;
    	   return s;
    }
    int main()
    {
    	   ll n;
           cin>>n;
           if(n==0)
           {
           	      cout<<0<<endl;
           	      return 0;
           }
    	   if(n==1||n==2)
    	   {
    	   	      cout<<1<<endl;
    	   	      return 0;
           } 
           else
           {
           	      yl a;
           	      a.n=2;
           	      a.g[1][1]=a.g[1][2]=a.g[2][1]=1;
           	      a.g[2][2]=0;
           	      yl s=Pow(a,n-1);
           	      s.n=2;
           	      //write(s);
           	      cout<<s.g[1][1]<<endl;
           	      return 0;
           }
    }
    
  • 相关阅读:
    内部类
    java的静态方法多态和匿名对象
    java的重载 和重写
    java多态成员的特点
    java 接口的概念
    linux时间修改-hwclock和date
    mysql配置主从复制和常见问题
    mysql日志种类、二进制日志模式、mysqlbinlog解析二进制日志
    mysql主从复制介绍
    mysql备份与还原-mysqldump备份、mysql与source还原
  • 原文地址:https://www.cnblogs.com/cjyyb/p/7197249.html
Copyright © 2011-2022 走看看