Fibonacci-ish(map去重搜索)

Problem G: Fibonacci-ish

Description

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. f(0)and f(1) are arbitrary
  3. f(n+2)=f(n+1)+f(n) 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.

Sample Input

3 1 2 -1

Sample Output

3

HINT

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

题意:

有n个数选择,f(0),f(1)任意取,从f(2)开始满足f(n+2)=f(n+1)+f(n)构成斐波拉契数列,求斐波拉契数列的最大长度。

思路:

首先对数组排序,用unique对相邻元素去重(实际上unique并没有删除元素,只是把重复元素放至数组末尾)

得到排序完全,无重复元素的数组最大元素个数:int index=unique(a,a+n)-a;

输入时用map统计每个数的重复次数:dis[a[i]]++;

接下来就是取起始两个元素(任意取)

所以用两个for循环即可实现

任意取得两个数字开始(注意: 3 5 和 5 3是两种完全不同的情况,看下这个就明白了: 3 5 8 13 ;5 3 8 11。所以两个for循环均从0开始)

接下来找第三个元素以及以后的元素。

x=a[i],y=a[j].

if(dis[x+y])则说明存在x+y 这个元素,ans+1,然后重复递归直到找不到下一个x+y。

最终的ans取值为max(ans,dis[a[i]+a[j]]+2)(ans表示之前情况的最大值,2代表起始两个元素,dis[a[i]+a[j]]则大有文章:代表从第三元素可以构成f(n+2)=f(n+1)+f(n)的最大长度-2)

AC代码:

#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<map>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#define mod 998244353;
#define Max 0x3f3f3f3f;
#define Min 0xc0c0c0c0;
#define mst(a) memset(a,0,sizeof(a))
#define f(i,a,b) for(int i=a;i<b;i++)
using namespace std;
typedef long long ll;
const int maxn=1005;
map<int,int>dis;
int n;
int a[maxn];

int sta(int x,int y){
    int ans=0;
    if(dis[x+y]){
        dis[x+y]--;             //取值后要把该元素次数-1
        ans=sta(y,y+x)+1;
        dis[x+y]++;             //进入下一次取值前要把该元素次数重新+1
    }
    return ans;
}
int main(){
    ios::sync_with_stdio(false);
    while(cin>>n){
        dis.clear();
        for(int i=0;i<n;i++){
            cin>>a[i];
            dis[a[i]]++;
        }
        sort(a,a+n);
        int index=unique(a,a+n)-a;
        int ans=0;
        for(int i=0;i<index;i++){
            for(int j=0;j<index;j++){       //取开始两个元素,全选择
                if(i==j && dis[a[i]]==1){      //取到同一个元素,但该元素只有一个终止本次循环
                    continue;
                }
                dis[a[i]]--;                        //取值后要把该元素次数-1
                dis[a[j]]--;
                ans=max(ans,sta(a[i],a[j])+2);      //取最大的斐波拉契数列长度
                dis[a[i]]++;                        //进入下一次取值前要把该元素次数重新+1
                dis[a[j]]++;
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/qq1013459920/article/details/82796595