http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1672
A sequence of integer numbers a1 , a2 , ..., an is called a Fibonacci sequence if ai = ai-2+ai-1 for all i=3,4,...,n.
Given a sequence of integer numbers c1 , c2 , ..., cm you have to find its longest Fibonacci subsequence.
Input | Output |
10 1 1 3 -1 2 0 5 -1 -1 8 |
5 1 -1 0 -1 -1 |
解题思路:
其实这是一道dp的题目,本来我们假设dp[i][j] 代表的是以a[i]和a[j]为开头的序列的长度。i从1~n而j从1~i-1,遍历,每对ij都作为相加看是否在已遍历过的i~n里有没有二者的和,如果有找出这个数的位置x,dp[j][i]=dp[i][x]+1.这样一来思路就清晰了。但是这里还有一个问题,我们整个问题下来是O(n^3)的复杂度,显然这对n==3000的数据量来说是无法接受的。因此我们在寻找a[i]+a[j]的时候运用哈希表复杂度为O(1),这样一来复杂度就降到的O(n^2), 就可以通过了。
附上hash_map的应用:http://blog.sina.com.cn/s/blog_4ac0a0d30100ukpp.html
#include <stdio.h> #include <string.h> #include <iostream> #include <hash_map> using namespace std; using __gnu_cxx::hash_map; #define N 3010 int a[N]; int dp[N][N]; int n; hash_map<int,int>mp; hash_map<int ,int >::iterator it; int main() { int test=0; while(~scanf("%d",&n)) { if(test!=0) printf("\n"); test++; for(int i=1; i<=n; i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) dp[i][j]=1; mp.clear(); int m=0,x,y; x=a[1]; for(int i=n;i>=1;i--) { for(int j=1;j<i;j++) { int k=a[i]+a[j]; it=mp.find(k); if(it!=mp.end()) { dp[j][i]=dp[i][it->second]+1; if(dp[j][i]>m) { m=dp[j][i]; x=j; y=i; } } } mp[a[i]]=i; } if(n==1) { printf("1\n%d\n",a[1]); continue; } if(n==2) { printf("2\n%d %d\n",a[1],a[2]); continue; } if(m==0) { printf("2\n%d %d\n",a[1],a[2]); } else { printf("%d\n",m+1); x=a[x],y=a[y]; printf("%d",x); for(int i=1;i<=m;i++) { printf(" %d",y); int z=x+y; x=y; y=z; } printf("\n"); } } return 0; } /* const int maxn=1000010; const int maxd=15; const int seed=30007; struct HASHMAP{ int head[seed],next[maxn],size; LL state[maxn]; LL f[maxn]; void clear(){ size=0; memset(head,-1,sizeof(head)); } void insert(LL st,LL ans){ int h=st%seed; for (int i=head[h];i!=-1;i=next[i]){ if (state[i]==st) { f[i]=max(f[i],ans); return; } } state[size]=st; f[size]=ans; next[size]=head[h]; head[h]=size++; } }hm[2];