CF 633 D 离散化+二分查找+暴力(还是要多学习学习呀,挺好的题目)

http://codeforces.com/contest/633/problem/D

D. Fibonacci-ish
time limit per test
3 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

Yash has recently learnt about the Fibonacci sequence and is very excited about it. He calls a sequence Fibonacci-ish if

  1. the sequence consists of at least two elements
  2. f0 and f1 are arbitrary
  3. fn + 2 = fn + 1 + fn for all n ≥ 0.

You are given some sequence of integers a1, a2, ..., an. Your task is rearrange elements of this sequence in such a way that its longest possible prefix is Fibonacci-ish sequence.

Input

The first line of the input contains a single integer n (2 ≤ n ≤ 1000) — the length of the sequence ai.

The second line contains n integers a1, a2, ..., an (|ai| ≤ 109).

Output

Print the length of the longest possible Fibonacci-ish prefix of the given sequence after rearrangement.

Examples
input
3
1 2 -1
output
3
input
5
28 35 7 14 21
output
4
Note

In the first sample, if we rearrange elements of the sequence as  - 121, the whole sequence ai would be Fibonacci-ish.

In the second sample, the optimal way to rearrange elements is 28.


题目大意:

给一个数列。根据斐波那契数列的定义,得出最长的子序列。


思路:

因为是斐波那契数列,所以说如果前两项知道了,那么后面的数列就排好了。题解上面还有写到,因为斐波那契数列是接近于2的幂的,所以说最长的子序列是90.但是可能存在全都是0的子序列。所以要特别注意一下。

这道题想了好久还是不会做就看了一下别人的题解。

主要的方法是如下,首先,因为前两项是不知道的,所以要枚举所有的可能性,那就是n^2。然后因为要通过lower_bound来寻找函数(表示这点想到了,但是之前自己写的时候不知道为什么TLE了),所以说之前要排序。然后就是离散化了,将状态进行压缩,用b数组来记录一下a数组中重复的值。

还有一点就是用pos[]数组来保存值。


感觉这道题学到了一下几点

①可以用pos数组来储存下标。表示以前都是用pos来储存的,没怎么用过数组。

②离散化。减少重复的搜索和代码的长度,优化了。

③大牛代码中的思考条件都十分的全面,尤其是if中,一定要好好学习。

④最后别忘了使用过一次以后都加回来。

下面给出临摹的代码:(本人现在也只有这水平了。。。不过还是有点不一样的啦)


#include<bits stdc="" h=""> using namespace std; const int maxn = 1000 + 5; int n, nn; int a[maxn], b[maxn]; int ans; void init(){ ans = 0; memset(a, 0, sizeof(a)); memset(b, 0, sizeof(b)); for (int i = 0; i < n; i++){ scanf("%d", a + i); ans += (a[i] == 0); } sort(a, a + n); ans = max(ans, 2); nn = 0; for (int i = 0; i < n; i++){ int t = i + 1; while (a[i] == a[t] && t < n) t++; a[nn] = a[i]; b[nn] = t - i; i = t - 1; nn++; } } void solve(){ int pos[maxn]; memset(pos, 0, sizeof(pos)); int f[maxn]; memset(f, 0, sizeof(f)); for (int i = 0; i < nn; i++){ f[0] = a[i]; b[i]--; for (int j = 0; j < nn; j++){ if (b[j] == 0 || (a[j] == 0 && a[i] == 0)){ continue; } f[1] = a[j]; b[j]--; for (int cnt = 2;; cnt++){ f[cnt] = f[cnt - 1] + f[cnt - 2]; pos[cnt] = lower_bound(a , a + nn, f[cnt]) - a; //不是单单就用pos,而是为了保存每一个的位置,使用pos[cnt] if (a[pos[cnt]] != f[cnt] || b[pos[cnt]] == 0 || pos[j] == nn){ while (cnt > 2){ cnt--;//顺序千万不能反了 b[pos[cnt]]++; } break; } ans = max(ans, cnt + 1); b[pos[cnt]]--; } b[j]++; } b[i]++; } printf("%d\n", ans); } int main(){ while (scanf("%d", &n) == 1){ init(); solve(); } return 0; } </bits>

你可能感兴趣的:(CF 633 D 离散化+二分查找+暴力(还是要多学习学习呀,挺好的题目))