標籤:ash rom otto 有趣 sam 計算 轉換 線性 快速定位
這是一道關於
題2好元素
2s
【問題描述】
小A一直認為,如果在一個由N個整數組成的數列{An}中,存在以下情況:
Am+An+Ap = Ai (1 <= m, n, p < i <= N , m,n,p可以相同),那麼Ai就是一個好元素。
現在小A有一個數列,請你計算數列中好元素的數目
【輸入格式】
第一行只有一個正整數N,意義如上。
第二行包含N個整數,表示數列{An}。
【輸出格式】
輸出一個整數,表示這個數列中好元素的個數。
【輸入範例】
|
Sample1 |
2
1 3 |
|
Sample2 |
6
1 2 3 5 7 10 |
|
Sample3 |
3
-1 2 0 |
【輸出範例】
|
Sample1 |
1 |
|
Sample2 |
4 |
|
Sample3 |
1 |
【資料範圍】
對於10%的資料1<=N<=10
對於40%的資料1<=N<=500 -10^5<=Ai<=10^5
對於70%的資料1<=N<=5000 -10^6<=Ai<=10^6
對於100%的資料1<=N<=5000 -10^9<=Ai<=10^9
分析:
寫這道題會探索資料非常大,而我們如果用n2的方法就會出現很有趣的現象,比如。炸時間。所以我們得用雜湊表來解決這個問題。
接下來講解一下雜湊表是什麼,及一些神奇的東西:
雜湊表,又名散列表,將線性表(或者一群大資料)運用某種散列函數,將資料轉化成一種關鍵字。關鍵字組成另一種可以用於快速尋找的表。快速定位,快速尋找是否存在該元素。。很多資料可能有相同的關鍵字,所以可以將關鍵字相同的資料連成一個新的線性表。
主要就是寫散列函數,而散列函數有很多種寫法。沒有固定的套路。有些可以講資料%一個大質數,將整個線性表疊在一個新的線性(但是有鏈表)的表裡。可以用領結表來表現。這有點繞其實就是的樣子。A[]代表將資料轉換成的關鍵字。後面連起來的東西就是關鍵字旗下的大資料。
當然有些也會用位元運算,將後面幾位相同的數組成一個線性序列。這道題其實就用這個方法。
。講一下這道題的大致做法:
從前往後枚舉,每次枚舉1,最後的重點,2,前面的一個點,而我們雜湊表裡放的就是兩個數之和,而我們在枚舉的時候。可以及時更新雜湊表。(在枚舉完一個新點,就將這個點與前面的每個點的值的和加入雜湊表)。其實就是枚舉。但是這裡最佳化時間最佳化的嚇人。所以可以過//hhhhh。
放出代碼:
#include<cstdio>#include<algorithm>using namespace std;#define M 4194303int line[5001];int n,cnt;int hashline[M+1];int vale[12600001];int next[12600001];void address(int w){ vale[++cnt]=w; next[cnt]=hashline[w & M]; hashline[w & M]=cnt; return ;}bool pure(int w){ for(int i=hashline[w & M]; i ; i=next[i]) { if(vale[i]==w)return true; } return false;}int ref(){ int ans=0; for(int i=1;i<=n;++i) { for(int j=1;j<i;++j) { if(pure(line[i]-line[j])) { ++ans; break; } } for(int j=1;j<=i;++j){ address(line[i]+line[j]); } } return ans;}int main(){ freopen("good.in","r",stdin); freopen("good.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;++i)scanf("%d",&line[i]); int ans=ref(); printf("%d",ans); fclose(stdin); fclose(stdout); return 0;}
就是這樣的東西。這個我認為比較好理解。還有就是。這個4194303數選的特別玄學。如果選小了。還過不了了?!!!!
noip類比賽 好元素 雜湊表的第一題