这道题裸的 dp 方程应该可以写的出来,我记录的状态如下:
dp[i][j] 表示以 ai 为第一个元素,aj 为第二个元素的斐波那契序列的最大长度,这样 i≤j 转移方程:
dp[i][j]=dp[j][k]+1
其中 ak=ai+aj
从后向前扫描,每次更新 dp 值后更新最大长度以及第一第二项,最后的答案直接根据第一第二项迭代即可
现在遇到的最大问题就是转移,裸的转移是 O(n) 的,直接从前向后扫一遍,找到第一个符合条件的 k,这样总的复杂度是枚举加上扫描,是 O(n3) 的,明显对 n 为 3000 的数据来说太大了,不可取。
后来想到了二叉树,嗯,就是 map,在树中维护值为 x 的最前位置,这样直接通过在树中找 ai+aj 的最前位置即可,后来想想也不对,复杂度是O(n2×logn) 的,对于 STL 的大常数不放心,算了一下 30002×lg3000 差不多108 数量级,会 TLE。又开始想转移能不能压缩。
最后想到 hash 的办法,因为转移无非就是在一个序列中找一个 x 对应的最前位置,直接将 x 进行 hash,对应的 hash 值的位置存放我们要的 x 对应的最前位置即可。
hash 函数乱写的 - -
发现其实数据重复的概率不大,没有优化,直接用了。。。
这样可以在近似 O(1) 的时间内找到我们要的值,转移加上枚举就是 O(n2) 的了