四個數列(二分求解)

2021-10-03 21:12:49 字數 2871 閱讀 6522

小明有四個數列 a,b,c,d,每個數列都有 n 個數字。小明從每個數列中各取出乙個數,他想知道有多少種方案使得 4 個數的和為 0。

ps:當乙個數列中有多個相同的數字的時候,把它們當做不同的數對待。

input:

第一行:n(代表數列中數字的個數) (1≤n≤4000)

接下來的 n 行中,第 i 行有四個數字,分別表示數列 a,b,c,d 中的第 i 個數字(數字不超過 2 的 28 次方)

output:

輸出不同組合的個數。

樣例輸入:

6-45

2242-16

-41-27

5630-36

53-3777-36

30-75-

4626-38

-1062-

32-54-

645

樣例輸出:

5
hint

樣例解釋:

(-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46),(-32, 30, -75, 77), (-32, -54, 56, 30).

首先拿到這個題目,最直接的就是暴力列舉,對每個數列列舉一遍,複雜度是n

4n^4

n4,而數字的個數為4×1

04

4×10^4

4×10

4,顯然會超時。那麼,通過分析題目,我們要找到使四個數的和為0的方案個數。即a+b

+c+d

=0

a+b+c+d=0

a+b+c+

d=0,我們可以通過移項,變成 :a+b

=−(c

+d

)a+b=-(c+d)

a+b=−(

c+d)

,這樣我們可以兩兩序列進行列舉,這樣得到的複雜度是n

2n^2

n2,顯然是可以接受的。

再進一步,如果我們要得到方案的個數,也就是求(c+

d)

(c+d)

(c+d

)的和序列中有多少數字和(a+

b)

(a+b)

(a+b

)和序列的相反數相等,那麼我們可以在列舉(c+

d)

(c+d)

(c+d

)的和時在(a+

b)

(a+b)

(a+b

)和序列中尋找有多少數字與其相反數相等,為了尋找這個數字,如果我們還是採用遍歷方法的話,那麼複雜度還是太高,那麼我們可以採用二分的方法進行查詢,可以將查詢的複雜度降低到log

nlogn

logn

級,這樣整個演算法的複雜度為n2l

ogn2

n^2logn^2

n2logn

2,是可以接受的。

為了要進行二分查詢,首先要保證(a+

b)

(a+b)

(a+b

)和序列是有序的,所以首先要對其進行排序,然後在列舉(c+

d)

(c+d)

(c+d

)的和時在其中進行查詢,可以使用兩個二分查詢函式,乙個是找到(c+

d)

(c+d)

(c+d

)相反數第一次在和序列**現的位置,另乙個是找到其在和序列中最後一次出現的位置,兩個相減,就是出現的次數,列舉完整個c和d序列,就能找到所有的方案。

對於乙個有序單調序列進行查詢,如果採用二分放法,將會大大降低演算法的複雜度,並且,如果乙個序列是單調的,都可以二分。

#include

#include

#include

#include

using

namespace std;

intthelow

(int x,

int left,

int right,

int v)

//尋找x第一次出現的位置

else

if(v[mid]

> x)

right = mid -1;

else

left = mid +1;

}return ans;

}int

thehigh

(int x,

int left,

int right,

int v)

//尋找x最後一次出現的位置

else

if(v[mid]

> x)

right = mid -1;

else

left = mid +1;

}return ans;

}int a[

4001];

int b[

4001];

int c[

4001];

int d[

4001];

int total[

16000001];

//存放a+b和的陣列

intmain()

int all = n * n;

int flag =0;

for(

int i =

0; i < n; i++)}

int number =0;

sort

(total,total+all)

;//排序

for(

int i =

0; i < n; i++)}

} cout << number;

}

二分 四個數列

zjm 有四個數列 a,b,c,d,每個數列都有 n 個數字。zjm 從每個數列中各取出乙個數,他想知道有多少種方案使得 4 個數的和為 0。當乙個數列中有多個相同的數字的時候,把它們當做不同的數對待。請你幫幫他吧!第一行 n 代表數列中數字的個數,1 n 4000 接下來的 n 行中,第 i 行有...

四個數列(二分法)

一 題目描述 zjm 有四個數列 a,b,c,d,每個數列都有 n 個數字。zjm 從每個數列中各取出乙個數,他想知道有多少種方案使得 4 個數的和為 0。當乙個數列中有多個相同的數字的時候,把它們當做不同的數對待。請你幫幫他吧!input 第一行 n 代表數列中數字的個數 1 n 4000 接下來...

week4 二分 四個數列

title zjm 有四個數列 a,b,c,d,每個數列都有 n 個數字。zjm 從每個數列中各取出乙個數,他想知道有多少種方案使得 4 個數的和為 0。當乙個數列中有多個相同的數字的時候,把它們當做不同的數對待。input 第一行 n 代表數列中數字的個數 1 n 4000 接下來的 n 行中,第...