3 4 17 233
Yes No Yes
附上该题对应的中文题
斐波那契数列的递归定义如下: 现在我们需要判断一个数是否能表示为斐波那契数列中的数的乘积。
有多组数据,第一行为数据组数T(T≤100,000)。 对于每组数据有一个整数n,表示要判断的数字。 0≤n≤1,000,000,000
对于每组数据,如果可以输出“Yes”,否则输出"No"。
3 4 17 233
Yes No Yes
出题人的解题思路:
Fibonacci序列在 109 范围内只有43个数,则它们的乘积不超过 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; }