HDU 1568 Fibonacci(大数前4位)

转载自:http://blog.****.net/thearcticocean/article/details/47615241

分析:x=1234567.求其前四位数: log10(x)=log10(1.234567)+6. 所以1.234567=10^(log10(x)-6). 1234 =(int) 10^(log10(x)-6)*1000. [6=length-4,length=(int)log10(x)+1]同时我们知道:

HDU 1568 Fibonacci(大数前4位)
对于小于10000的数字可以存储在数组中直接输出,大于等于10000的数字则用上式计算。我们能知道:i<21 f[i]<1e4.当n=21时[(1-sqrt(5))/2]^n --> 0.618^n 0.618自乘5次就会退一个10进制等级。所以n>=21可以忽略[(1-sqrt(5))/2]^n。log10(x)=log10[ 1/sqrt(5)*[(1+sqrt(5))/2]^n ]=log10(1/sqrt(5))+n*log10(1+sqrt(5))/2).
例如:
log10(12345678)=log10(1.2345678*10^7)=log10(1.2345678)+7
log10(1.2345678)就是log10(12345678)的小数部分.
log10(1.2345678)=qs
10^qs=1.2345678,
要求该数的前4位,则将 1.2345678*1000即可。

#include <iostream>  
#include <cstdio>  
#include <cmath>  
using namespace std;  
const int maxn=50; //,mod=1e4;  
int f[maxn];  
int main()  
{  
    f[0]=0;  
    f[1]=1;  
    for(int i=2;i<21;i++){  
        f[i]=f[i-1]+f[i-2];  //i<21 f[i]<1e4.  
    }  
    int n;  
    double q1=log10(1/sqrt(5)),q2=log10((1+sqrt(5))/2);  
    while(cin>>n){  
        if(n<21){   printf("%d
",f[n]); continue; }  
        double t=q1+n*q2;  
        double p=t-(int)t;  
        double ans1=pow(10,p);  
        cout<<(int)(ans1*1000)<<endl;  
    }  
    return 0;  
}