题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3117
解题思路:
很显然费波纳数的后四位存在周期,通过测试可以发现后四位的周期为15000,所以后四位可以打表得出,
前四位是参考了别人的思路才做出来的。
因为费波纳数f[n] = 1/sqrt(5)(((1+sqrt(5))/2)^n+((1-sqrt(5))/2)^n).
很显然当n非常大的时候(1-sqrt(5))/2)^n非常的小以至于可以忽略,假设F[n]可以表示成 t * 10^k(t是一个小数),那么对于F[n]取对数log10,答案就为log10 t + K,此时很明显log10 t<1,于是我们去除整数部分,就得到了log10 t ,再用pow(10,log10 t)我们就还原回了t。将t×1000就得到了F[n]的前四位。
题目实现:
#include<stdio.h> #include<math.h> #define aa (sqrt(5.0)+1.0)/2 int fib_h[15000],Fib[40] = {0,1,1,2,3,5,8,13},n; int main() { fib_h[0] = 0 ;fib_h[1] = 1; //费波那数后四位 for(int i = 2; i <= 14999; i++) { fib_h[i] = (fib_h[i-1] + fib_h[i-2])%10000; } for(i = 7; i < 40; i++) Fib[i] = Fib[i-1] + Fib[i-2]; while(scanf("%d",&n) != EOF) { if(n < 40) printf("%d\n",Fib[n]); else { double ans = -0.5*(log10(5.0))+n*log10(aa); ans-=(int)ans; ans=pow(10.0,ans); while(ans<1000) ans*=10; printf("%d...",(int)ans); printf("%4.4d\n",fib_h[n%15000]); } } return 0; }