1. 程式人生 > >CF 633D【斐波那契】

CF 633D【斐波那契】

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【斐波那契】