斐波那契数列很容易理解,不过由它演变的题目很多。。。
一般出的题目给的数据都很大,就是让你找规律。。。
前两天校赛的时候出了一道题目。。 不死兔子。。参见zzuli-oj 1478题
就是让求F(n)%m,然后n会很大,能达到10^8;
这样的题目很明显的就是找循环节。。
不过当时不知道是和前面的两三项进行比较, 以为还会和中间的相等(就是从中间开始循环), 写了一个双层for循环,直到最后,程序也没能运行出来。。
后来听同学说只需要和前面2,3项进行判断就行, 至于为什么呢,我也无从得知。。。
最后写了一层for循环,很容易的就找到了循环节,AC了。。。。
还有一种类型的题目。。。Fibonacci 。。。 参见hdu -oj 1568
这道题是让求F(n)的最前面4项,比上面的那道题目有难度。。
没想到什么好的方法,参见了资料:
先看对数的性质,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.....)
取完对数
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
所以可以写成log10(an)=-0.5*log10(5.0)+((double)n)*log(f)/log(10.0);
最后取其小数部分。
看了这个资料,很惊讶,斐波那契数列竟然存在神马递推公式。。。
然后根据资料很容易就把这个题目给A了。。
代码:
# include<stdio.h> # include<math.h> int f[25]; # define PI (sqrt(5.0)+1.0)/2 int main() { int i,n; double bit; f[0]=0; f[1]=1; for(i=2;i<=20;i++) { f[i]=f[i-1]+f[i-2]; } while(scanf("%d",&n)!=EOF) { if(n<=20) printf("%d\n",f[n]); else { bit=-0.5*log10(5.0) + ((double)n)*log10(PI); bit = bit-(int)bit; bit= pow(10,bit); while(bit<1000) bit*=10; printf("%d\n",(int)bit); } } return 0; }