HDU5167Fibonacci

本文介绍了一个算法问题,即判断一个数是否能由斐波那契数列中的数相乘得到。提供了两种解决方案,一种是通过暴力打表的方式预处理所有可能的组合并使用队列和映射来存储结果;另一种是采用递归分解的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Fibonacci

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2127    Accepted Submission(s): 546


Problem Description
Following is the recursive definition of Fibonacci sequence:
Fi=01Fi1+Fi2i = 0i = 1i > 1

Now we need to check whether a number can be expressed as the product of numbers in the Fibonacci sequence.
 

Input
There is a number T shows there are T test cases below. (T100,000)
For each test case , the first line contains a integers n , which means the number need to be checked. 
0n1,000,000,000
 

Output
For each case output "Yes" or "No".
 

Sample Input
3 4 17 233
 

Sample Output
Yes No Yes
 

不懂题意的小伙伴 去BEST CODE 里面看看中文版的:http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=564&pid=1002


看到  0n1,000,000,000;

T100,000;

这么大的数据,不要被吓到,不敢下手了;其实我们直接打表看看斐波那契数列,可以发现f[46]>10亿,那么满足要

求的最大的斐波那契数列就是到f[45]了;对于十亿这个数据的处理我已经处理完了,只要一个简单的打表得到所有的

f[n]就好了;然后就是处理T这个数据了,我们也可以直接用暴力打表的方法;得到这45个斐波那契数列所能组成的乘

积;

暴力打表:用队列实现,用map表示他们的映射关系,也就是是否满足题意;不能用for循环去打表实现,那样循环重复

次数太多,效率太慢,还是会超时的;

还可以用递归分解,得到;


给出代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
using namespace std;
long long f[10005];
map<long long, bool> mp;
queue<long long> q;
//暴力打表;
void F()
{
	f[0] = 0;
	f[1] = 1;
	mp[0] = true;
	for (int i = 2; i <= 46; i++)
	{
		f[i] = f[i - 1] + f[i - 2];
		mp[f[i]] = true;
		q.push(f[i]);
	}
	while (!q.empty())
	{
		long long t = q.front();
		q.pop();
		for (int i = 2; i <= 46; i++)
		{
			if (t*f[i]>1000000000L)break;
			if (mp[t*f[i]])continue;
			mp[t*f[i]] = true;
			q.push(t*f[i]);
		}
	}
}
int main()
{
	F();
	long long n;
	int T;
	scanf("%d",&T);
	while (T--)
	{
		scanf("%lld", &n);
		if (mp[n])printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}
//递归求解;
/*
void F()
{
	f[0] = 0;
	f[1] = 1;
	for (int i = 2; i < 46; i++)
	{
		f[i] = f[i - 1] + f[i - 2];
	}
}
int FG(long long n, int x)
{
	if (n <= 3)return 1;
	for (int i = 3; i <= x; i++)
	{
		if (n%f[i] == 0)
		{
			if (FG(n/f[i], i))return 1;
		}
	}
	return 0;
}
int main()
{

	F();
	int T;
	long long n;
	scanf("%d",&T);
	while (T--)
	{
		scanf("%lld",&n);
		if (FG(n, 45))
			printf("Yes\n");
		else 
			printf("No\n");
	}
	return 0;
}
*/




T100,000
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值