C 雜湊 二分 佇列例題 數對個數

2021-07-26 08:00:06 字數 1744 閱讀 5386

給出一串數以及乙個數字 c,要求計算出所有 a-b=c 的數對的個數。規定:不同位置的數字一樣的數對算不同的數對。

第一行包括 2 個非負整數 n 和 c(c≠0),中間用空格隔開。

第二行有 n 個整數,中間用空格隔開,作為要求處理的那串數。

輸出一行,表示該串數中包含的所有滿足 a-b=c 的數對的個數。

輸入  [複製]

4 1 

1 1 2 3

輸出

3

【資料範圍】

對於 50% 的資料,0 < n <= 200;

對於 70% 的資料,0 < n <= 2000;

對於 100% 的資料,0 < n <= 200000。

所有輸入資料都在 c++ 的 int 範圍內。

演算法1:佇列

換一種思路來減少要判斷的數對。對於a-b=c而言,如果a-b>c,很顯然對於同乙個a,不需要再查詢更小的b;

如果a-b

1、對n個數排序,排序後統計相同數字出現的次數,把相同的數字都縮成乙個數字,並記錄下總數;

2、視排序後的數隊同時為a隊和b隊,指標都指向第乙個元素;

3、若指標所指的a-b>c,即b不能再減小了,那麼a隊的指標就往後移一位,減小a值;若指標所指的a-b

4、若有a-b=c,那麼就在答案上增加當前的數對個數,注意加入相同數的個數。

#include#include#include#include#include#include#includeusing namespace std;

int num[200020];

int n,c,all;

int ab[200020];

int tot[1000000][2];

long long ans=0;

int main()

else num[all-1]++;

} }for(int i=1;i<=n;i++)

i+=num[tot[ab[i]][1]];

} cout<

演算法2:二分查詢

先不考慮乙個數字重複多次出現的情況,對於乙個數a,又已知與a的差為c,也就是說當a和c確定下來的時候,另乙個數b的大小也就確定下來了。所以我們可以第一遍列舉a,然後再在剩下的數中找確定的b。

由於b的值已經確定,可以用二分查詢來降低複雜度。具體做法如下:

先對n個數進行排序,排序後統計相同數字出現的次數(也可以把相同的數字都縮成乙個數字,並記錄下總數)。然後列舉n個數,再對排完序後的n個數進行二分查詢,並累計答案。

這樣o(n^2)就可以降為o(n log n)。

#include#define mod 300007

using namespace std;

int hash[mod*2],data[mod*2]; //hash[i]表示第i個數的值;data[i]表示數字i的個數

int locate(int x) //雜湊表儲存x

int n,c,i,j,a[mod],ans;

int main()

for(i=1;i<=n;++i) //a[i]=b,列舉b

printf("%d\n",ans);

return 0;

}

演算法3:樸素演算法

列舉a數與b數,把a-b=c數對都找出來,很明顯,對於n<=200000的資料這種做法必定會超時。

7 28 猴子選大王 20分 (佇列)

一群猴子要選新猴王。新猴王的選擇方法是 讓n只候選猴子圍成一圈,從某位置起順序編號為1 n號。從第1號開始報數,每輪從1報到3,凡報到3的猴子即退出圈子,接著又從緊鄰的下乙隻猴子開始同樣的報數。如此不斷迴圈,最後剩下的乙隻猴子就選為猴王。請問是原來第幾號猴子當選猴王?輸入格式 輸入在一行中給乙個正整...

白騎士的移動 20分 佇列實現

小s第一次接觸西洋棋。他發現西洋棋中的knight棋子的移動方式和中國象棋中的馬類似,移動方式如圖所示。於是小s在棋盤上隨意擺上了一些棋子,其中包括一枚白騎士 一枚黑皇后 若干黑戰車和若干黑主教。小s想知道,如何能在避開黑戰車和黑主教的攻擊範圍的前提下,花費更少的步數吃掉黑皇后。注1 戰車的攻擊範圍...

洛谷P1102 A B數對 二分 雜湊

出題是一件痛苦的事情!相同的題目看多了也會有審美疲勞,於是我捨棄了大家所熟悉的 a b problem,改用 a b 了哈哈!好吧,題目是這樣的 給出一串數以及乙個數字 cc,要求計算出所有 a b ca b c 的數對的個數 不同位置的數字一樣的數對算不同的數對 輸入共兩行。第一行,兩個整數 n,...