斐波那契数列很容易理解,不过由它演变的题目很多。。。

一般出的题目给的数据都很大,就是让你找规律。。。

前两天校赛的时候出了一道题目。。 不死兔子。。参见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;
}



posted on 2011-04-13 13:22  奋斗青春  阅读(374)  评论(0编辑  收藏  举报