HDU1568_求fibonacci的前四位

题目大意:

          求fibonacci数列的前面四位,注意f[0] = 0;

解题思路:

          凡是要求数的前面几位的,都可以用两边求对数的思想。让我想起了,m = n^n.要求n的前面一位。这个时候用对数,

lg(m) = n*lg(n), m = pow(10, n*lg(n)),之后求n*lg(n)的小数部分,因为整数部分为10^P(p代表整数),全都为10000……,而小数部分则为10^B(B代表小数部分),所以要取几位,就去小数那里取即可。

         这是网络上摘来的,写得very good:

        先看对数的性质,loga(b^c)=c*loga(b),loga(b*c)=loga(b)+loga(c);
        假设给出一个数10234432,那么log10(10234432)=log10(1.0234432*10^7)=log10(1.0234432)+7;
          log10(1.0234432)就是log10(10234432)的小数部分.
          log10(1.0234432)=0.010063744
         10^0.010063744=1.023443198
         那么要取几位就很明显了吧~
         先取对数(对10取),然后得到结果的小数部分bit,pow(10.0,bit)以后如果答案还是<1000那么就一直乘10。
         注意偶先处理了0~20项是为了方便处理~

     这题要利用到数列的公式:an=(1/√5) * [((1+√5)/2)^n-((1-√5)/2)^n](n=1,2,3.....)
代码:

#include<iostream>
#include<cmath>
const double N1 = (1.0 + sqrt(5.0)) / 2.0;
const double N2 = (1.0 - sqrt(5.0)) / 2.0;
using namespace std;
int main(void)
{
    int n;
    int f[21];
    f[0] = 0;
    f[1] = 1;
    f[2] = 1;
    for(int i = 3; i < 21; i++)
        f[i] = f[i-1] + f[i-2];
    while(scanf("%d", &n) == 1)
    {
        if(n <= 20)
        {
            printf("%d\n", f[n]);
            continue;
        }
        double temp1, temp2, ans;
        temp1 = log10(1.0 / sqrt(5.0));
        temp2 = (double)n * log10(N1) + log10(1.0 - pow(N2, (double)n));
        ans = temp1 + temp2;
        ans = ans - (int)ans;

        ans = pow((double)10, ans);
        // printf("%lf\n", ans);
        // printf("%lf\n", ans);
        printf("%d\n", (int)(ans * 1000));
    }
    return 0;
}

TLE代码:
#include<iostream>
using namespace std;
const int MAX = 10005;
char str[MAX], str1[MAX], str2[MAX];

void add(char a[], char b[], char c[])
{
    memset(c, '0', sizeof(c));
    int len1, len2, len;
    len1 = strlen(a);
    len2 = strlen(b);
    for(int i = len1 - 1, j = 0; i >= 0; i--, j++)
        c[j] = a[i];
    for(int i = len2 - 1, j = 0; i >= 0; i--, j++)
        c[j] += b[i] - '0';
    len = len1 >= len2 ? len1 : len2;

    for(int i = 0; i < len; i++)
    {
        if(c[i] > '9')
        {
            c[i] -= 10;
            c[i+1] ++;
        }
    }
    if(c[len] > '0')
        len++;
    c[len] = '\0';
    strrev(c);
    //for(int i = 0; i < len; i++)
    // printf("%c", c[i]);
    //printf("\n");
}

int main(void)
{
    int n;
    int cas;

    /*strcpy(str1, "132424");
    strcpy(str2, "123424234");
    add(str1, str2, str);*/
    scanf("%d", &cas);
    while(cas--)
    {
        // scanf("%d", &n);

        for(int n = 1; n < 30; n++)
        {
            strcpy(str1, "1");
            strcpy(str2, "1");
            if(n == 1 || n == 2)
            {
                printf("1\n");
                continue;
            }
            for(int i = 3; i <= n; i++)
            {
                memset(str, '0', sizeof(str));
                add(str1, str2, str);
                strcpy(str1, str2);
                strcpy(str2, str);
            }
            printf("%s\n", str);
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/cchun/p/2620893.html