【Manthan, Codefest 16D】【暴力+去重or特判】Fibonacci-ish n个数组成最长斐波那契数列的长度

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  - 1, 2, 1, the whole sequence ai would be Fibonacci-ish.

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

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b>a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b<a)a = b; }
const int N = 1010, M = 0, Z = 1e9 + 7, ms63 = 0x3f3f3f3f;
int n;
int a[N];
int ans;
map<int,int>mop;
LL f[N];
void go(int x, int y)
{
	//if (x == 0 && y == 0){gmax(ans, mop[0]);return;}
	--mop[x];
	--mop[y];
	f[1] = x;
	f[2] = y;
	int i; for (i = 3;; ++i)
	{
		f[i] = f[i - 1] + f[i - 2];
		if (mop.find(f[i]) != mop.end() && mop[f[i]])--mop[f[i]];
		else break;
	}
	gmax(ans, i - 1);
	for (int j = 1; j < i; ++j)++mop[f[j]];
}
pair<int, int>b[N*N];
int main()
{
	while (~scanf("%d", &n))
	{
		mop.clear();
		for (int i = 1; i <= n; ++i)scanf("%d", &a[i]), ++mop[a[i]];
		int m = 0;
		for (int i = 1; i <= n; ++i)
		{
			for (int j = 1; j <= n; ++j)if(j!=i)
			{
				b[++m] = MP(a[i], a[j]);
			}
		}
		b[0].first = 2e9;
		sort(b + 1, b + m + 1);
		ans = 0;
		for (int i = 1; i <= m; ++i)
		{
			if (b[i].first != b[i - 1].first || b[i].second != b[i - 1].second)
			{
				go(b[i]. first, b[i].second);
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}
/*
【trick&&吐槽】
1,这道题在一个傻叉错误上栽了3次跟头。
就是因为我读错题了,
把 arbitrary 当做是"不相同的"的意思,而这实际是"任意的"的意思。
知道后来才发现。= =

2,不要忘了枚举开头的时候,要判定i!=j >_< 囧

【题意】
有n(2<=n<=1000)个数,每个数的权值都在[-1e9,1e9]范围内。
我们要把它们按照一定方式排列。
使得最前几位是斐波那契数列,且长度尽可能长
问你这最长的斐波那契数列的长度是多少

【类型】
暴力枚举

【分析】
首先,我们发现,只要我们枚举了前2位,后面的所有位自然也可以算出来了。
如果我们用mop[]存一个数字的数量,那么,我们就可以验证这2位作为开头的可行性。
然而,这个复杂度看似是O(n^3 log(n) )的。

不过,给定的数字都是-1e9~1e9范围的数,
于是,如果开头2个数都是整数或者负数,我们的斐波那契项数最多不过30

如果是1正1负作为开头的话,且和为正,继续向下迭代的话,我们发现也是向小缩小,
而且为了保证正负交替,依然需要|abs(fib[i])|>=2|abs(fib[i+1])|。
于是不过30次就变成0。
而只有0 0作为开头,答案才会被延长到超过60项。
我们可以把所有开头pair做去重,或者特判0 0,都可以顺利AC这道题。

【时间复杂度&&优化】
O(n^2 * 30 * log(n))

【数据】
有一组数据
-1 1
-2 2
-3 3
-4 4
-5 5
-6 6
...
0 0 0 0 0...

对于这组数据,我们其实只有1000个长达1000(≈)个数列,也不会TLE啦

不过特判还是没有把询问去重快哦

*/


你可能感兴趣的:(codeforces,暴力,题库-CF,STL-map)