题目链接:
hdu: http://acm.hdu.edu.cn/showproblem.php?pid=5167
题意:
给你一个x,判断x能不能由斐波那契数列中的数相乘得到(一个数可以重复使用)
题解:
1、筛法
首先,小于10^9的斐波那契数很少,就42个(不包括0,1),对于给定的x能同时成为它的因子的斐波那契数更少,所以可以暴力考虑所有能整除x的斐波那契数组成的集合的所有子集。
但是,对于每个子集做筛法的时候必须从大的数开始筛(质因数分解可以随便筛是因为一个数的质因数分解具有唯一性,但这里并不具有唯一性),因为大的数比小的数更特别,它可能具有小的数不具备的组成x的质因子,如果它具备独特质因子,那它就要筛到不能筛为止,如果它不具备独特质因子,它多筛了也不影响的,所以从大到小的做保证了正确的分解不会丢失。
68=2*34=2*2*17,如果从小到大筛,会把2全筛了,剩下个17是没办法筛掉的,而如从后往前则会先筛掉34,再筛掉一个2,这样就可以了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 typedef long long LL; 7 8 const int maxn = 111; 9 10 int fib[maxn]; 11 12 int tot; 13 void get_fib() { 14 fib[0] = 2, fib[1] = 3; 15 for (tot = 2;; tot++) { 16 fib[tot] = fib[tot - 1] + fib[tot - 2]; 17 if (fib[tot] >1000000000) break; 18 } 19 } 20 21 int di[maxn], n; 22 23 void init() { 24 n = 0; 25 } 26 27 int main() { 28 get_fib(); 29 int tc; 30 scanf("%d", &tc); 31 while (tc--) { 32 init(); 33 int x; 34 scanf("%d", &x); 35 if (x == 0||x==1) { 36 puts("Yes"); continue; 37 } 38 for (int i = 0; i < tot; i++) { 39 if (x%fib[i] == 0) { 40 di[n++] = fib[i]; 41 } 42 } 43 bool su = false; 44 for (int stat = 0; stat < (1 << n); stat++) { 45 int tmp = x; 46 for (int i = n-1; i >=0; i--) { 47 if (stat&(1 << i)) { 48 while (tmp%di[i] == 0) tmp /= di[i]; 49 } 50 } 51 if (tmp == 1) { 52 su = true; break; 53 } 54 } 55 if (su) puts("Yes"); 56 else puts("No"); 57 } 58 return 0; 59 } 60 /* 61 68 62 */
2、直接暴搜
看完题解哭晕。。
而且跑的溜溜的orz
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 typedef long long LL; 7 8 const int maxn = 111; 9 10 int fib[maxn]; 11 12 int tot; 13 void get_fib() { 14 fib[0] = 2, fib[1] = 3; 15 for (tot = 2;; tot++) { 16 fib[tot] = fib[tot - 1] + fib[tot - 2]; 17 if (fib[tot] >1000000000) break; 18 } 19 } 20 21 int di[maxn], n; 22 23 bool dfs(int cur, int x) { 24 if (x == 1) return true; 25 if (cur == n) return false; 26 if (dfs(cur + 1, x)) return true; 27 28 if (x%di[cur]==0) { 29 int tmp = x; 30 while (tmp%di[cur] == 0) { 31 tmp /= di[cur]; 32 //printf("tmp:%d ", tmp); 33 if (dfs(cur + 1, tmp)) return true; 34 } 35 } 36 return false; 37 } 38 39 void init() { 40 n = 0; 41 } 42 43 int main() { 44 get_fib(); 45 int tc; 46 scanf("%d", &tc); 47 while (tc--) { 48 init(); 49 int x; 50 scanf("%d", &x); 51 if (x == 0||x==1) { 52 puts("Yes"); continue; 53 } 54 for (int i = 0; i < tot; i++) { 55 if (x%fib[i] == 0) { 56 di[n++] = fib[i]; 57 } 58 } 59 //printf("n:%d ", n); 60 if (dfs(0,x)) puts("Yes"); 61 else puts("No"); 62 } 63 return 0; 64 }