CF 633D【斐波那契】
阿新 • • 發佈:2018-05-31
for lB 分享 line pre pan title OS 出現次數
狂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 }
CF 633D【斐波那契】