代码改变世界

hdc fibonacci number 1568

2012-04-14 20:47  youxin  阅读(388)  评论(0编辑  收藏  举报

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)这样语句来判断是否正确的给所有的变量赋值了,正确的话才能使用这个变量参与运算,这样才能提高我们代码的安全性,所以这个返回值也是大有用途的