您的位置:首页 > 其它

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

2016-03-26 22:03 507 查看
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

the sequence consists of at least two elements

f0 and f1 are
arbitrary

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  - 1, 2, 1,
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>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: