题目地址: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;
}