zoukankan      html  css  js  c++  java
  • hdc fibonacci number 1568

    hdc1568

    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个数字,就全部输出)。
     
    大数要用到fibonacci的通项公式::an=(1/√5) * [((1+√5)/2)^n-((1-√5)/2)^n](n=1,2,3.....)
    还有对数log的作用:

    对数log()的作用,先让我们回忆一下log 的运算性质吧~

    1)log(a*b)=log(a)+log(b);  2)log(a/b)=log(a)-log(b);

    其实在数学里面,log可以求一个大数的科学计数法的数值部分,比如说123456

    首先log10(1234567)=log10(1.234567*10^6)=log10(1.234567)+6; 然后log10(1.234567)就是log10(1234567)的小数位

    然后10^log10(1.234567)=1.234567,所以通过这样的转换 我们可以很巧妙的得到了一个很大的数的科学计数法的表示值!

    然后您要取4位就拿4位!要多少位就拿多少位!

    取10的对数为:

    log10(an)=-0.5*log10(5.0)+((double)n)*log(f)/log(10.0)+log10(1-((1-√5)/(1+√5))^n)

    其中f=(sqrt(5.0)+1.0)/2.0;
      log10(1-((1-√5)/(1+√5))^n)->0 趋近于0
    所以可以写成log10(an)=-0.5*log10(5.0)+((double)n)*log(f)/log(10.0); 为什么是log(10.0) 运用了对数的性质。
    最后取其小数部分。对于10^X,X为一个实数,可以分解为一个整数和一个小数的和,X=Z+P,即10^X=10^(Z+P)
    =10^Z * 10^P,(0<=P<1).显然10^Z不会影响到10^X的数字。最后只要取10^P的前四位数。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int f[21] = {0, 1, 1};
    
    int main()
    {
        int n;
        for(int i = 2; i < 21; ++i)
            f[i] = f[i - 1] + f[i - 2];
        while(scanf("%d", &n) != EOF)
        {
            if(n <= 20)//区别与其他多于四位的答案,20是6765,21时 10946
            {
                printf("%d\n", f[n]);
                continue;
            }
            else
            {
                double temp = -0.5 * log(5.0) / log(10.0) + ((double)n) * log((sqrt(5.0)+1.0)/2.0) / log(10.0);
                temp -= floor(temp);
                temp = pow(10.0, temp);
                while(temp < 1000)
                    temp *= 10;
                printf("%d\n", (int)temp);
            }
        }
        return 0;
    }

    令一版本:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    int s[21]={0,1,1,2};
    const double f=((double)sqrt(5.0)+1)/2.0;
    void get_Fibonacci(int x){
        if(x<=20)
            printf("%d\n",s[x]);
        else{
            double ans=(-0.5)*log(5.0)/log(10.0)+(double(x))*log(f)/log(10.0);
            ans=ans-floor(ans);
            double k=pow(10.0,ans);
            //cout<<"k= "<<k<<endl;
            while(k<1000.0)
                k*=10.0;
            printf("%d\n",(int)k);
        }
         
    }
    int main(){
        int x,i;
        for(i=3;i<=20;i++)
            s[i]=s[i-1]+s[i-2];
          //在这里为了区别其他多于4位的答案我先把4位以内的
         //都计算好存起来!
        while(~scanf("%d",&x)){ //为什么加~,不加可不可以?-1 补码11111111,取反后为0,退出,不能为!,eof为-1;还是没退出
            if(x==0){
                printf("0\n");
                continue;   
            }
            get_Fibonacci(x);
        }
        return 0;
    }

     c++ log double log ( double x );

    float log ( float x );

    long double log( long double x );

    Compute natural logarithm Returns the natural logarithm of x. (以e为底

    double log10 ( double x );

    float log10 ( float x );

    long double log10 ( long double x );

    Compute common logarithm Returns the common (base-10) logarithm of x.

    scanf的返回值问题:

    msdn解释:Both scanf and wscanf return the number of fields successfully converted and assigned; the return value does not include fields that were read but not assigned. A return value of 0 indicates that no fields were assigned.
    The return value is EOF for an error or if the end-of-file character or the end-of-string character is nocountered in the first attempt to read a character.

    scanf()函数返回成功赋值的数据项数,读到文件末尾出错时则返回EOF。

     

    scanf()函数返回成功赋值的数据项数,读到文件末尾出错时则返回EOF。
      如:
      scanf("%d,%d", &a, &b);
      如果a和b都被成功读入,那么scanf的返回值就是2
      如果只有a被成功读入,返回值为1
      如果a和b都未被成功读入,返回值为0
      如果遇到错误或遇到end of file,返回值为EOF。
      且返回值为int型.
      例:使用scanf函数输入数据。
      #include<stdio.h>
      int main()
      {
      int a,b,c;
      printf("输入 a, b, c\n");
      scanf("%d,%d,%d", &a, &b, &c);
      printf("a = %d b = %d c = %d\n", a, b, c);
      fflush(stdin);
      return 0;
      }
      注意上面的scanf("%d,%d,%d",&a,&b,&c);中%d,%d,%d之间有逗号,在输入数据时也要加逗号(如果不加除了第一个数正确外,其余都错)如果去掉逗号,输入时就不用逗号,而用空格,tab键或回车键将各个数据隔开

    其实scanf()的返回值对我们来说也很有用的,比如我们在使用这个函数进行接收值时,我们很必要知道对要给赋值的变量是否正确的赋值成功了,所以可以使用if(scanf("%d,%d",&a,&b)==2)这样语句来判断是否正确的给所有的变量赋值了,正确的话才能使用这个变量参与运算,这样才能提高我们代码的安全性,所以这个返回值也是大有用途的

      

  • 相关阅读:
    2020系统综合实践 第五次实践作业
    2020系统综合实践 第4次实践作业
    2020系统综合实践 第3次实践作业
    2020系统综合实践 第2次实践作业
    2020系统综合实践 第1次实践作业
    wireshark大作业——负载均衡
    第07组 Beta版本演示
    第07组 Beta冲刺(4/4)
    软工实践个人总结
    第03组 Beta冲刺(5/5)
  • 原文地址:https://www.cnblogs.com/youxin/p/2447555.html
Copyright © 2011-2022 走看看