CF 633D【斐波那契】

狂WA巨坑题

题意:给出n<=1000个数,能组成的类似斐波那契的数列最长长度是多少(fn=fn-1+fn-2,n>=2)

solution:看起来是一道相当高端的数论题,还是D题?我现在都没现场切过D 没想到做法就是暴力?不过暴力可证复杂度OK

感觉枚举一下前两项,一直往下找,这样用个map维护一下复杂度也是n^3logn啊

不过打个斐波那契数列的表就能发现,因为每个值范围[-1e9,1e9],所以即使数列第一个和第二个是绝对值很小的两个1也会在45项左右停止,这样的话就算50项,复杂度好像可以,不过坑点巨多

坑点1:要把0特殊拿出来,因为如果前两项是0整个数列就全都是0,绝对值不上升,毒瘤数据稳稳卡成n^3logn

坑点2:如果有0要放进去1个,因为可能会有 0,x,x,……或x,0,x……这种操作

坑点3:元素有重啊!答案数列也可能有重,所以map不能存bool要存int

坑点4:map映射元素的个数,所以在原始数组中枚举前两项要去重。如果不去重,极端情况下所有数45个一组正好一个斐波那契数列,然后重复20遍,这样n^2*45,但是不要忘了还有map logn大约是10可能会被卡(99点果然被卡)

坑点5:去完重后,注意数列前两个可以相同,前提是该数出现次数>1

有些神奇刚才unique之前没sort(不能完全去重)竟然过了。。。

复制代码
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<map>
 4 #include<algorithm>
 5 using namespace std;  6 map <int,int> M,T;//int开始写成bool了  7 int n,A[2020],ans;  8 int main(){  9 scanf("%d",&n); 10 int i,j; 11 for (i=1;i<=n;i++){ 12 scanf("%d",&A[i]); 13 if (!A[i]) i--,n--,ans++; 14 else M[A[i]]++; 15  } 16 if (ans) n++,M[0]=1;//有0的话给去掉0的数列加个0 17 sort(A+1,A+n+1);//忘了 18 n=unique(A+1,A+n+1)-A-1;//去重提高效率 19 for (i=1;i<=n;i++) 20 for (i=1;i<=n;i++) for (j=1;j<=n;j++) 21 if (i==j&&M[A[i]]<2) continue; 22 //不能直接i=j就退出因为数列前两个可能一样 23 else{ 24 int cur,a1=A[i],a2=A[j],sum=2; 25  T.clear(); 26 T[a1]++; T[a2]++; 27 while (1){ 28 cur=a1+a2; 29 if (T[cur]==M[cur]) break; 30 T[cur]++; a1=a2; a2=cur; sum++; 31  } 32 ans=max(ans,sum); 33  } 34 cout<<ans; 35 }
复制代码

猜你喜欢

转载自www.cnblogs.com/Pedestrian6/p/9118835.html