(求大数的前n位数字)Fabonacci -- HDOJ 1568

Fibonacci

Problem Description
2007年到来了。经过2006年一年的修炼,数学神童zouyu终于把0到100000000的Fibonacci数列
(f[0]=0,f[1]=1;f[i] = f[i-1]+f=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

Author
daringQQ

Source
Happy 2007

Recommend
8600

总结:
以前遇到的斐波那契的问题 是让求第n个斐波那契的后几位数字的,而这次是求前几位数字的,这里就用到了斐波那契的通项公式

这里写图片描述

1/(根号下5) 与后面的中括号是分离的

取一个大数字的前几位可以采用这样的方法:
例如:123456789
double A = log10(123456789)
= log10(1.23456789*10^8)
= log10(1.23456789) + log10(10^8)
= log10(1.23456789) + 8

log10(1.23456789) 必定是小于1的数

double B = A - floor(A) = log10(1.23456789)
那么10^B 就为 1.23456789,这样,无论取前几位,我们都可以为所欲为,为所欲为了。

接下来我们就可以对斐波那契的通项进行取对数了
[(1-√5)/2]^20 = 0.000066106961351896
[(1-√5)/2]^24 = 0.0000096448756784497
假设A=log10(Fn) = 1.2345678
我们要的是B=0.2345678,所以A数字的小数点后四位一定要保证正确
从第n为24开始,在任何情况下都不会影响小数点后面第四位的数字了,
但是事实上,从第21位开始,小数点后第四位的数字就不再受后面的数字影响了。也就是说,前n《=20 的时候,是不能套用公式的,打表即可。这时候,从第21位斐波那契数开始,位数上升到五位数,这是巧合吗??

log10( (1/√5)*{[(1+√5)/2]^n - [(1-√5)/2]^n} )

=-0.5*log10(5) + n *log10((1+5^0.5)/2)

然后根据前面介绍的方法计算即可

# include <iostream>
# include <stdio.h>
# include <algorithm>
# include <string>
# include <math.h>

using namespace std;

int main(void)
{
    long long f1 = 1,f2 = 1;
    int f[25];
    f[0] = 0,f[1] = 1;
    for(int i=2; i<=20; ++i)
        f[i] = f[i-1] + f[i-2];

    int n;
    while(scanf("%d",&n) != EOF)
    {
        if(n <= 20)
            cout << f[n] <<endl;
        else
        {
            double ans = -0.5*log10(5) + n*log10(((1+sqrt(5))/2.0));
            ans = ans - floor(ans);
            ans = pow(10,ans);
            ans *= 1000;
            int res = (int )ans;
            cout << res <<endl;
        }
    }



    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值