ACM1568

题目:求斐波那契数列,输入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;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值