题目大意
给你一个长为$m(mle 3000)$的数列,求最长Fibonacci子序列。
简要题解
DP即可,因为头两个随便选,所以考虑设$f[i][j]$表示以$a_i,a_j$开始的Fibonacci子序列最长长度为多少,只需要从$f[j][k],a_k=a_i+a_j$转移,关键在于找到$k$,map和hash_map都TLE了,最后手写了一个HashTable,Accept。
有一个细节就是转移的顺序,先从后往前枚举第一维$i$,再从$i-1$到$0$枚举第二维$j$,就可以避免每次清空HashTable。
输出答案没必要保存DP信息(不然会MLE),直接由Fibonacci前两项就可以全部推出来了,我个智障。
1 #include <bits/stdc++.h> 2 using namespace std; 3 namespace my_header { 4 #define pb push_back 5 #define mp make_pair 6 #define pir pair<int, int> 7 #define vec vector<int> 8 #define pc putchar 9 #define clr(t) memset(t, 0, sizeof t) 10 #define pse(t, v) memset(t, v, sizeof t) 11 #define bl puts("") 12 #define wn(x) wr(x), bl 13 #define ws(x) wr(x), pc(' ') 14 const int INF = 0x3f3f3f3f; 15 typedef long long LL; 16 typedef double DB; 17 inline char gchar() { 18 char ret = getchar(); 19 for(; (ret == ' ' || ret == ' ' || ret == ' ') && ret != EOF; ret = getchar()); 20 return ret; } 21 template<class T> inline void fr(T &ret, char c = ' ', int flg = 1) { 22 for(c = getchar(); (c < '0' || '9' < c) && c != '-'; c = getchar()); 23 if (c == '-') { flg = -1; c = getchar(); } 24 for(ret = 0; '0' <= c && c <= '9'; c = getchar()) 25 ret = ret * 10 + c - '0'; 26 ret = ret * flg; } 27 inline int fr() { int t; fr(t); return t; } 28 template<class T> inline void fr(T&a, T&b) { fr(a), fr(b); } 29 template<class T> inline void fr(T&a, T&b, T&c) { fr(a), fr(b), fr(c); } 30 template<class T> inline char wr(T a, int b = 10, bool p = 1) { 31 return a < 0 ? pc('-'), wr(-a, b, 0) : (a == 0 ? (p ? pc('0') : p) : 32 (wr(a/b, b, 0), pc('0' + a % b))); 33 } 34 template<class T> inline void wt(T a) { wn(a); } 35 template<class T> inline void wt(T a, T b) { ws(a), wn(b); } 36 template<class T> inline void wt(T a, T b, T c) { ws(a), ws(b), wn(c); } 37 template<class T> inline void wt(T a, T b, T c, T d) { ws(a), ws(b), ws(c), wn(d); } 38 template<class T> inline T gcd(T a, T b) { 39 return b == 0 ? a : gcd(b, a % b); } 40 template<class T> inline T fpw(T b, T i, T _m, T r = 1) { 41 for(; i; i >>= 1, b = b * b % _m) 42 if(i & 1) r = r * b % _m; 43 return r; } 44 }; 45 using namespace my_header; 46 47 const int MAXN = 3000 + 3; 48 int a[MAXN], n; 49 short f[MAXN][MAXN]; 50 51 struct HashTable { 52 static const int MOD = 100019; 53 static const int HASHSIZE = 3333; 54 int h[MOD], nxt[HASHSIZE], key[HASHSIZE], val[HASHSIZE], cnt; 55 HashTable() { 56 memset(h, -1, sizeof h); 57 cnt = 0; 58 } 59 int getHash(int p) { 60 return (p % MOD + MOD) % MOD; 61 } 62 void insert(int k, int v) { 63 int t = getHash(k); 64 val[cnt] = v; 65 key[cnt] = k; 66 nxt[cnt] = h[t]; 67 h[t] = cnt++; 68 } 69 int find(int k) { 70 int t = getHash(k); 71 for (int i = h[t]; i != -1; i = nxt[i]) { 72 if (key[i] == k) 73 return val[i]; 74 } 75 return 0; 76 } 77 } pos; 78 79 int main() { 80 #ifdef lol 81 freopen("C.in", "r", stdin); 82 freopen("C.out", "w", stdout); 83 #else 84 freopen("fibsubseq.in", "r", stdin); 85 freopen("fibsubseq.out", "w", stdout); 86 #endif 87 fr(n); 88 for (int i = 1; i <= n; ++i) 89 fr(a[i]); 90 for (int i = n; 0 < i; --i) { 91 for (int j = i - 1; 0 < j; --j) { 92 int t = pos.find(a[i] + a[j]); 93 if (f[i][t] + 1 > f[j][i]) 94 f[j][i] = f[i][t] + 1; 95 } 96 pos.insert(a[i], i); 97 } 98 int ans = 0, ri, rj; 99 for (int i = 1; i <= n; ++i) 100 for (int j = i + 1; j <= n; ++j) 101 if (f[i][j] >= ans) { 102 ans = f[i][j]; 103 ri = a[i]; 104 rj = a[j]; 105 } 106 wt(ans + 1); 107 if (ans == 0) { 108 wt(a[1]); 109 return 0; 110 } 111 for (int i = 0; i <= ans; ++i) { 112 ws(ri); 113 int t = ri + rj; 114 ri = rj; 115 rj = t; 116 } 117 puts(""); 118 119 return 0; 120 }