小明有四個數列 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 行中,第...