题意:给一个数n,问这个数n(<=10^9)是否能表示为斐波那契数列中的数的乘积。
思路:先预处理得到斐波那契数列,先判断了一下,n<=10^9,该范围大概有40来个数,先预处理保存这些数即可。
接下来就进行DFS,但是每次枚举的范围都不变的话会超时的,因此需要每次缩小枚举的范围,这也是本题关键的一个剪枝技巧。
每次枚举的时候都从最大的斐波那契数开始,倒着进行枚举,这样下一次出现的斐波那契数一定比上一次的小,从而缩小了枚举范围。
下面贴代码,关键要注意DFS中的for循环:
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <ctype.h>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#define eps 1e-8
#define INF 0x7fffffff
#define PI acos(-1.0)
#define seed 31//131,1313
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
LL f[50];
void init() {
f[0] = 0;
f[1] = 1;
for(int i = 2; i <= 45; i++) {
f[i] = f[i-1] + f[i-2];
}
}
bool dfs(LL n, int x) {
if(n <= 3) {
return true;
}
for(int i = x; i >=3; i--) {
if(n % f[i] == 0) {
if(dfs(n / f[i], i)) {
return true;
}
}
}
return false;
}
int main() {
init();
int T;
LL n;
scanf("%d",&T);
while(T--) {
scanf("%I64d",&n);
if(dfs(n, 45)) {
printf("Yes\n");
}else {
printf("No\n");
}
}
return 0;
}