题目给定一个数n,非常大,n个这样的int型会超memory,要求fib[n],超过四位的数只要输出前4位
首先考虑传统的O(n)算法求fibonacci数,显然先求出所有数然后保存下来会超过题目要求的memory,这种方法不适用,即我们无法将数保存下来然后输出,因此只能对每个要求的n,单独求出前四位,因此考虑直接使用公式
,当然直接代公式是不可能,从只需要输出前4位这个条件入手,
假设给出一个数10234432,那么log10(10234432)=log10(1.0234432*10^7)=log10(1.0234432)+7;
想到10234432=1.0234432*10^7,如果我们能得到1.0234432这个数,那么这道题就很好解决了
log10(1.0234432)就是log10(10234432)的小数部分,只要将这个数减去它自身的下取整,就得到了小数部分
然后再求10^,这样就去除了那个10^7。
log10(1.0234432)=0.010063744
10^0.010063744=1.023443198
将小数点后移动至1023.xxxxx,取整后就是所要的答案
套用fibonacci公式时,由于n很大我们可以取近似
Fn=1/sqrt(5) * (1+sqrt(5)/2)^n
详见代码:
#include<iostream>
#include<cmath>
using namespace std;
int fib[21];
int main(){
fib[0]=0;
fib[1]=1;
for(int i=2;i<=20;i++){
fib[i]=fib[i-1]+fib[i-2];
}
int n;
while(cin>>n){
if(n<=20)
cout<<fib[n]<<endl;
else{
double e1=1/sqrt(5);
double e2=(1+sqrt(5))/2;
double ans=log(e1)/log(10) + n*log(e2)/(log(10));
ans=ans-floor(ans);
ans=pow(10,ans);
while(ans<1000)
ans*=10;
cout<<(int)ans<<endl;
}
}
return 0;
}