对于斐波拉契经典问题,我们都非常熟悉,通过递推公式F(n) = F(n - 1) + F(n - 2),我们可以在线性时间内求出第n项F(n),现在考虑斐波拉契的加强版,我们要求的项数n的范围为int范围内的非负整数,请设计一个高效算法,计算第n项F(n-1)。第一个斐波拉契数为F(0) = 1。
给定一个非负整数,请返回斐波拉契数列的第n项,为了防止溢出,请将结果Mod 1000000007。
测试样例:
3
返回:2
对于斐波拉契经典问题,我们都非常熟悉,通过递推公式F(n) = F(n - 1) + F(n - 2),我们可以在线性时间内求出第n项F(n),现在考虑斐波拉契的加强版,我们要求的项数n的范围为int范围内的非负整数,请设计一个高效算法,计算第n项F(n-1)。第一个斐波拉契数为F(0) = 1。
给定一个非负整数,请返回斐波拉契数列的第n项,为了防止溢出,请将结果Mod 1000000007。
3
返回:2
简洁、高效 的 递归解法,目前没有发现比我这个更简洁的代码了,50 ms,1238K
思路 :找规律,可用数学归纳法证明;
初始值:f(0) = 1, f(1) = 1, f(2) = 2, f(3) = 3, f(4) = 5...
f(10)
= f(9)+ f(8) = f(1)f(9)+f(0)f(8)
=2f(8)+ f(7) = f(2)f(8)+f(1)f(7)
=3f(7)+2f(6)= f(3)f(7)+f(2)f(6)
Map<Integer,Integer> mp = new HashMap<Integer, Integer>();
public int getNthNumber(int n) {
if (n==1||n==0)return 1;
if (n==2)return 2;
if (mp.containsKey(n))return mp.get(n);//避免重复计算
long fn1=getNthNumber(n/2+1); // f(n+1)
long fn_1=getNthNumber(n/2-1); // f(n-1)
long fn=getNthNumber(n/2); // f(n)
if (n%2==1) // F(2n+1) = F(n+1) F(n) + F(n) F(n-1), n>=1
mp.put(n,(int)((fn*fn1+fn*fn_1)%1000000007));
else // F(2n) = F(n) F(n) + F(n-1) F(n-1), n>=1
mp.put(n,(int)((fn*fn+fn_1*fn_1)%1000000007));
return mp.get(n);
}
参考大佬的代码!
class Fibonacci {
public:
void MultMetri(long long base1[2][2],long long base2[2][2])
{
long long tmp[2][2]={0};
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
tmp[i][j]=(base1[i][0]*base2[0][j]+base1[i][1]*base2[1][j])%1000000007;
}
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
base1[i][j]=tmp[i][j];
}
}
int getNthNumber(int n) {
long long base[2][2]={{1,1},{1,0}};
long long ret[2][2]={{1,0},{1,0}};
while(n)
{
if(n%2)
MultMetri(ret,base);
MultMetri(base,base);
n=n/2;
}
return (int)(ret[0][0]);
}
};
import java.util.*;
public class Fibonacci {
public int getNthNumber(int n) {
// write code here
long[][] base={{1,1},{1,0}};
long[][] ret={{1,0},{0,1}};
while(n!=0){
if(n%2==1)
ret=MultMetri(ret,base);
base=MultMetri(base,base);
n=n>>1;
}
return (int)(ret[0][0]);
}
public static long[][] MultMetri(long[][] ret,long[][] base){
long[][] tmp=new long[2][2];
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
tmp[i][j]=(ret[i][0]*base[0][j]+ret[i][1]*base[1][j])%1000000007;
for(int k=0;k<2;k++)
for(int q=0;q<2;q++)
ret[k][q]=tmp[k][q];
return ret;
}
}
来个python版本的,代码相当简洁
# -*- coding:utf-8 -*-
class Fibonacci:
def getNthNumber(self, n):
res=base=[[1,1],[1,0]]#结果项和基底项
surplus=[[1,0],[0,1]]#surplus存储剩余项
while(n>1):
if n&1:
surplus=self.mutiply(surplus,res)
res=self.mutiply(res,res)
n=n>>1
res=self.mutiply(res, surplus)
return res[0][0]%1000000007
def mutiply(self,a,b):#矩阵乘法
temp=[[0,0],[0,0]]
for i in range(len(a)):
for j in range(len(b)):
for k in range(len(temp)):
temp[i][j]+=a[i][k]*b[k][j]%1000000007
return temp
#include<bits/stdc++.h>
typedef long long ll;
class Fibonacci {
public:
int getNthNumber(int n) {
// write code here
if(mp.count(n))
return mp[n];
if(n==0)
{
mp[0]=1;
return mp[0];
}
if(n==1)
{
mp[1]=1;
return mp[1];
}
mp[n]=((ll)getNthNumber(n/2)*getNthNumber(n-n/2)%MOD +(ll)getNthNumber(n/2-1)*getNthNumber(n-n/2-1)%MOD)%MOD;
return mp[n];
}
private:
unordered_map<int,int> mp;
const int MOD=1000000007;
}; class Fibonacci {
public: void Mul(long long a[2][2], long long b[2][2]) { long long t[2][2] = {0}; for(int i=0;i<2;i++) for(int j=0;j<2;j++) t[i][j] = (a[i][0]*b[0][j] + a[i][1]*b[1][j])%(1000000007); for(int i=0;i<2;i++) for(int j=0;j<2;j++) a[i][j] = t[i][j]; }
int getNthNumber(int n) {
long long base[2][2] = {{1,1},{1,0}};
long long ret[2][2] = {{1,0},{1,0}};
while(n)
{
if(n&1)
Mul(ret, base);
Mul(base, base);
n>>=1; } return ret[0][0];
}
};
class Fibonacci {
public:
void multi(long long a[2][2], long long b[2][2])
{
long long r[2][2];
r[0][0] = a[0][0] * b[0][0] + a[0][1] * b[1][0];
r[0][1] = a[0][0] * b[0][1] + a[0][1] * b[1][1];
r[1][0] = a[1][0] * b[0][0] + a[1][1] * b[1][0];
r[1][1] = a[1][0] * b[0][1] + a[1][1] * b[1][1];
a[0][0] = r[0][0] % 1000000007;
a[0][1] = r[0][1] % 1000000007;
a[1][0] = r[1][0] % 1000000007;
a[1][1] = r[1][1] % 1000000007;
}
int getNthNumber(int n) {
long long tmpA[2][2] = {
{ 1, 1 },
{ 1, 0 }
};
long long tmpB[2][2] = {
{ 1, 0 },
{ 0, 1 }
};
for (; n > 1; n = n / 2)
{
if (n & 1 == 1)
{
multi(tmpB,tmpA);
}
multi(tmpA, tmpA);
}
multi(tmpA, tmpB);
return tmpA[0][0] ;
}
};
参考的程云老师的课程(第9次课)。
class Fibonacci {
public:
static const long long MOD =1000000007;
int getNthNumber(int n) {
// write code here
int a=1,b=1;
vector< vector<long long> > matrix(2);
vector< vector<long long> > res(2);
res[0].resize(2);
res[1].resize(2);
const int m[2][2]={{1,1},{1,0}};
for( int i=0; i<2; ++i )
for( int j=0; j<2; ++j )
matrix[i].push_back(m[i][j]);
res[0][0]=res[1][1]=1;
res[0][1]=res[1][0]=0;
while( n )
{
if( n&1 ) res=multiply(res,matrix);
matrix=multiply(matrix,matrix);
n >>= 1;
}
return (res[1][0]%MOD+res[1][1]%MOD)%MOD;
}
private:
vector< vector<long long> > multiply ( vector< vector<long long> >& a, vector< vector<long long> >& b )
{
vector< vector<long long> > temp(2);
for( int i=0; i<2; i++ )
temp[i].resize(2);
for( int i=0; i<2; i++ )
{
for( int j=0; j<2; j++ )
{
temp[i][j] = ((a[i][0]%MOD * b[0][j]%MOD )%MOD + (a[i][1]%MOD * b[1][j]%MOD )%MOD)%MOD;
}
}
return temp;
}
};
#define ll long long
class Fibonacci {
public:
ll mod = 1e9+7;
vector<vector<ll>> matrixPower(vector<vector<ll>>m,int p)
{
vector<vector<ll>>ret(2,vector<ll>(2,0));
for(int i=0;i<2;++i)
ret[i][i] = 1;
while(p)
{
if(p%2)
{
ret = multiMatrix(ret,m);
}
m = multiMatrix(m,m);
p/=2;
}
return ret;
}
vector<vector<ll>> multiMatrix(vector<vector<ll>> m1,vector<vector<ll>> m2)
{
vector<vector<ll>>ans(2,vector<ll>(2,0));
for(int i=0;i<2;++i)
for(int j=0;j<2;++j)
{
ans[i][j] = ((m1[i][0]%mod)*(m2[0][j]%mod) + (m1[i][1]%mod)*(m2[1][j]%mod))%mod;
}
return ans;
}
int getNthNumber(int n) {
// write code here
n+=1;
if(n==1||n==2) return 1;
long long m[2][2] = {{1,1},{1,0}};
vector<vector<ll>>base(2,vector<ll>(2,0));
for(int i=0;i<2;++i)
for(int j=0;j<2;++j)
base[i][j] = m[i][j];
vector<vector<ll>> res = matrixPower(base,n-2);
return (res[0][0]+res[1][0])%mod;
}
};