题目:求斐波那契数列,输入n(0 <= n <= 100000000),求出f[n](f[n] = f[n-1]+f[n-2]),若结果超过4位,只需输出前4位
刚开始用动态规划做。提交了一下,WA。想了一想,这结果太大了,肯定有溢出,然后不知道怎么写了,就去看了一下Discuss。
知道了:
1.斐波那契数列的通项公式f[n]={[(1+√5) / 2]^n - [(1-√5) / 2]^n} /√5 【√5表示根号5】
2.还是用到了对数的方法。
对于很大的数字,可以用对数的方式尝试一下,特别是这种只取前几位的。
解析:
当n大时,[(1-√5) / 2]^n值很小,可以忽略不计 (n = 20时,[(1-√5) / 2]^20 = 0.000066107,已经不会影响到最高的那4位了)
所以估算 f[n] = 10^(log10([(1+√5) / 2]^n / √5 )) = 10^(n * log10((1+√5) / 2))) - log10(√5))。求出(n * log10((1+√5) / 2))) - log10(√5))的小数部分k,计算10^k,再处理一下,得到需要输出的位数。
#include <stdio.h>
#include <math.h>
int main()
{
int n,f[21],i;
double num,k,result;
f[0] = 0;
f[1] = 1;
for(i = 2;i < 21;i++)
f[i] = f[i-1] + f[i-2];//n小时,用后面的方法算误差大,所以分开计算
while(scanf("%d",&n) != EOF)
{
if(n <= 20)
{
printf("%d\n",f[n]);
continue;
}
num = n * log10((1 + sqrt(5.0)) / 2.0) - log10(sqrt(5.0));
k = num - (int)num;
result = pow(10.0,k);
while(result < 1000)
result *= 10;
printf("%d\n",(int)result);
}
return 0;
}