HDU 5167 Fibonacci——BestCoder Round #28(搜索+预处理)

Fibonacci

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)


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
 

Source
BestCoder Round #28
 
/************************************************************************/

附上该题对应的中文题

Fibonacci

 
 Accepts: 40
 
 Submissions: 1024
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 65536/65536 K (Java/Others)
问题描述
斐波那契数列的递归定义如下:


现在我们需要判断一个数是否能表示为斐波那契数列中的数的乘积。
输入描述
有多组数据,第一行为数据组数TTT \leq 100,000T100,000)。
对于每组数据有一个整数nn,表示要判断的数字。
0 \leq n \leq 1,000,000,0000n1,000,000,000
输出描述
对于每组数据,如果可以输出“Yes”,否则输出"No"。
输入样例
3
4
17
233
输出样例
Yes
No
Yes
/****************************************************/

出题人的解题思路:

Fibonacci序列在 10^9109 范围内只有43个数,则它们的乘积不超过 10^9109 的数也不会很多,直接搜索即可。
拿到这道题的时候,理所当然的,预处理一下,先把109 内的斐波那契数求出来存好,

然后从大到小遍历斐波那契数,能整除的先除尽,直到遍历结束,判断最后的结果是不是1(n=0的情况另外考虑)。

game over ,过程看起来一气呵成,但是恭喜,最后会和我一样收获到一个WA

然后苦思幂想不得其果,感觉与别人用搜索的方法过程其实没什么差别,但是差别就在这里。

或许直到你找到那么一组数据,才会甘心

n=1008

按我们初始想到的方法,1008=144*7,然后因为7不是斐波那契数,所以No,但是,1008偏偏就能表示成斐波那契数的乘积

1008=2*2*2*2*3*21

这回终于知道为什么错了,在我们从大到小找斐波那契因子的时候,一旦能被整除,会先除尽,

这样就导致大的斐波那契数带走了小的斐波那契数的因子,例如144带走了21里的因子3,导致剩下的7不是斐波那契数

所以还是乖乖用搜索吧,当然若是你把其理解成递归能够好懂一点,也无大碍。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<string>
#include<algorithm>
#include<iostream>
#define exp 1e-10
using namespace std;
const int N = 50;
const int inf = 1000000000;
int s[N];
bool judge(int n,int k)
{
    if(n==1)
        return true;
    for(int i=k;i>2;i--)
        if(n%s[i]==0&&judge(n/s[i],i))
            return true;
    return false;
}
int main()
{
    int t,i,n;
    s[0]=0,s[1]=1;
    for(i=2;i<45;i++)
        s[i]=s[i-1]+s[i-2];
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        if(!n)
            puts("Yes");
        else if(judge(n,44))
            puts("Yes");
        else
            puts("No");
    }
    return 0;
}

菜鸟成长记

你可能感兴趣的:(算法,搜索,ACM)