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 i b ( n ) = 1 5 × [ ( 1 + 5 2 ) n ( 1 5 2 ) n ] Fib(n)=\frac{1}{\sqrt{5}}\times [(\frac{1+\sqrt{5}}{2})^{n}-(\frac{1-\sqrt{5}}{2})^{n}]​ Fib(n)=5 1×[(21+5 )n(215 )n]

公式具体推导过程看百度百科:斐波那契数列

由于通项公式在 n n n较小时精度较低且 n &lt; 21 n&lt;21 n<21 F i b ( n ) Fib(n) Fib(n)也仅仅只有四位数,所以当 n &lt; 21 n&lt;21 n<21时利用递推式求解,当 n &gt; 20 n&gt;20 n>20时再利用通项公式求解,利用对数求数字前 4 4 4位的方法具体参考HDU 1060 Leftmost Digit

由于 F i b ( n ) Fib(n) Fib(n)数据很大,所以先转换通项公式后取对数。

F i b ( n ) = 1 5 × [ ( 1 + 5 2 ) n ( 1 5 2 ) n ] Fib(n)=\frac{1}{\sqrt{5}}\times [(\frac{1+\sqrt{5}}{2})^{n}-(\frac{1-\sqrt{5}}{2})^{n}] Fib(n)=5 1×[(21+5 )n(215 )n]

F i b ( n ) = 1 5 × [ ( 1 + 5 2 ) n ( 1 + 5 2 × 1 5 1 + 5 ) n ] \therefore Fib(n)=\frac{1}{\sqrt{5}}\times [(\frac{1+\sqrt{5}}{2})^{n}-(\frac{1+\sqrt{5}}{2}\times \frac{1-\sqrt{5}}{1+\sqrt{5}})^{n}] Fib(n)=5 1×[(21+5 )n(21+5 ×1+5 15 )n]

F i b ( n ) = 1 5 × ( 1 + 5 2 ) n × [ 1 ( 1 5 1 + 5 ) n ] \therefore Fib(n)=\frac{1}{\sqrt{5}}\times (\frac{1+\sqrt{5}}{2})^{n}\times [1-(\frac{1-\sqrt{5}}{1+\sqrt{5}})^{n}] Fib(n)=5 1×(21+5 )n×[1(1+5 15 )n]

l o g 10 F i b ( n ) = l o g 10 1 5 × ( 1 + 5 2 ) n × [ 1 ( 1 5 1 + 5 ) n ] \therefore log_{10}{Fib(n)}=log_{10}{\frac{1}{\sqrt{5}}\times (\frac{1+\sqrt{5}}{2})^{n}\times [1-(\frac{1-\sqrt{5}}{1+\sqrt{5}})^{n}]} log10Fib(n)=log105 1×(21+5 )n×[1(1+5 15 )n]

l o g 10 F i b ( n ) l o g 10 1 5 + n × l o g 10 1 + 5 2 \therefore log_{10}{Fib(n)}\approx log_{10}{\frac{1}{\sqrt{5}}} + n\times log_{10}{\frac{1+\sqrt{5}}{2}} log10Fib(n)log105 1+n×log1021+5

AC代码:

#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define mp make_pair
#define lowbit(x) (x&(-x))
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<double,double> PDD;
typedef pair<ll,ll> PLL;
const int INF = 0x3f3f3f3f;
const int maxn = 1e3 + 5;
const int mod = 1e9 + 7;
const double eps = 1e-8;
const double pi = asin(1.0) * 2;
const double e = 2.718281828459;
bool Finish_read;
template<class T>inline void read(T &x) {
    Finish_read = 0;
    x = 0;
    int f = 1;
    char ch = getchar();
    while (!isdigit(ch)) {
        if (ch == '-') {
            f = -1;
        }
        if (ch == EOF) {
            return;
        }
        ch = getchar();
    }
    while (isdigit(ch)) {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    x *= f;
    Finish_read = 1;
};

int main(int argc, char *argv[]) {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    int f[21];
    mem(f, 0);
    f[1] = 1;
    for (int i = 2; i < 21; ++i) {
        f[i] = f[i - 1] + f[i - 2];
    }
    int n;
    while (~scanf("%d", &n)) {
        if (n < 21) {
            printf("%d\n", f[n]);
            continue;
        }
        double ans = log10(1.0 / sqrt(5.0)) + n * log10((1.0 + sqrt(5.0)) / 2.0);
        ans -= ll(ans);
        ans = pow(10, ans);
        while (ans < 1000) {
            ans *= 10;
        }
        printf("%d\n", int(ans));
    }
#ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
    system("gedit out.txt");
#endif
    return 0;
}