HDU 1568:http://acm.hdu.edu.cn/game/entry/problem/show.php?chapterid=2§ionid=2&problemid=1
题目大意是算出第0~100000000个斐波那契数列的高4位数。
高4位不同于低4位,要考虑进位问题,不能直接取模。
时间要求1s,空间要求32MB,O(n)的方法肯定超时,也不能存数组。就只剩下公式了。
斐波那契数列的公式是:Fib[n]=
对于第40个斐波那契数10234432,
log10(10234432)=log10(1.0234432*10^7)=log10(1.0234432)+7,
取其小数部分log10(1.0234432)=0.010063744,
10^0.010063744=1.023443198,结果×1000取整,即为高4位。
将a[n]取log10(Fib[n])=
其中第三部分非常小,当n很大时趋近于0,可以忽略掉。
但是当n较小时,Fib[n]不足4位,为了方便处理,单独拿出来用Fib[i]=Fib[i-1]+Fib[i-2]处理。
源代码:
#include <stdio.h>
#include <math.h>
#define N 20
int Fib[N+1];
//a(n)=(√5/5)*{[(1+√5)/2]^n - [(1-√5)/2]^n}
int main()
{
int i=0;
Fib[0]=0,Fib[1]=1;
for(i=2;i<=N;++i)
Fib[i]=Fib[i-1]+Fib[i-2];
int n,m;
double x,y,z,w;
x=log10(5.0)/2;
y=log10((1+sqrt(5.0))/2);
//z=(sqrt(5.0)-3)/2;
while(scanf("%d",&n)!=EOF)
{
if(n<=20){
printf("%d\n",Fib[n]);
continue;
}
//w=n*y+log10(1-pow(z,n))-x;
w=n*y-x;
w=w-(int)w;
w=pow(10,w);
m=(int)(w*1000);
printf("%d\n",m);
}
return 0;
}