hdu 1568 Fibonacci 数学公式

Fibonacci

Problem Description
2007年到来了。经过2006年一年的修炼,数学神童zouyu终于把0到100000000的Fibonacci数列
(f[0]=0,f[1]=1;f[i] = f[i-1]+f[i-2](i>=2))的值全部给背了下来。
接下来,CodeStar决定要考考他,于是每问他一个数字,他就要把答案说出来,不过有的数字太长了。所以规定超过4位的只要说出前4位就可以了,可是CodeStar自己又记不住。于是他决定编写一个程序来测验zouyu说的是否正确。
 
Input
输入若干数字n(0 <= n <= 100000000),每个数字一行。读到文件尾。
 
Output
输出f[n]的前4个数字(若不足4个数字,就全部输出)。
 
Sample Input
0 1 2 3 4 5 35 36 37 38 39 40
 
Sample Output
0 1 1 2 3 5 9227 1493 2415 3908 6324 1023
 
思路:很明显不是递推题,那就是在线算法,给一个快速求一个即可~~
我们由递推关系F[n] = F[n-1] + F[n-2].使用数学数列的消除(数归)应该可以得到F[n]与n之间的关系式:
同时利用对10取对数的方法,即可将数值的位数化为科学计算法形式,那么在通过pow(10,小数部分)的逆向就可以得到F[n]的前几位。这时只需累乘10(即还原前几位的过程)满足范围即可;
细节:里面先计算了前40为数值。由于之后取对数化简时,我们从中括号中提了[(1+sqrt(5)/2]^n,之后变成
这时当n较大时,最后一项趋于0,所以只需计算前两项即可;
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<vector>
#include<cmath>
#include<stdlib.h>
#include<time.h>
#include<stack>
#include<set>
#include<map>
#include<queue>
using namespace std;
#define rep0(i,l,r) for(int i = (l);i < (r);i++)
#define rep1(i,l,r) for(int i = (l);i <= (r);i++)
#define rep_0(i,r,l) for(int i = (r);i > (l);i--)
#define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
#define MS0(a) memset(a,0,sizeof(a))
#define MS1(a) memset(a,-1,sizeof(a))
#define MSi(a) memset(a,0x3f,sizeof(a))
#define inf 0x3f3f3f3f
#define lson l, m, rt << 1
#define rson m+1, r, rt << 1|1
typedef pair<int,int> PII;
#define A first
#define B second
#define MK make_pair
typedef __int64 ll;
template<typename T>
void read1(T &m)
{
    T x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    m = x*f;
}
template<typename T>
void read2(T &a,T &b){read1(a);read1(b);}
template<typename T>
void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);}
template<typename T>
void out(T a)
{
    if(a>9) out(a/10);
    putchar(a%10+'0');
}
ll F[40],n;
const double dot = (sqrt(5.)+1)/2;
int main()
{
    F[0] = 0;F[1] = 1;
    rep1(i,2,40) F[i] = F[i-1]+F[i-2];
    while(scanf("%d",&n) == 1){
        if(n <= 40){
            ll ans = F[n];
            while(ans >= 10000) ans /= 10;
            out(ans);
        }
        else{
            double ans = -0.5*log10(5)+1.*n*log10(dot);
            ans -= int(ans);//忽略了10^n,只是数值
            ans = pow(10,ans);
            while(ans < 1000) ans *= 10;
            printf("%d",int(ans));
        }
        puts("");
    }
    return 0;
}

 

posted @ 2016-03-15 08:50  hxer  阅读(223)  评论(0编辑  收藏  举报