zjm 有四個數列 a,b,c,d,每個數列都有 n 個數字。zjm 從每個數列中各取出乙個數,他想知道有多少種方案使得 4 個數的和為 0。
當乙個數列中有多個相同的數字的時候,把它們當做不同的數對待。
請你幫幫他吧!
input
第一行:n(代表數列中數字的個數) (1≤n≤4000)
接下來的 n 行中,第 i 行有四個數字,分別表示數列 a,b,c,d 中的第 i 個數字(數字不超過 2 的 28 次方)
output
輸出不同組合的個數。
sample input
6-45 22 42 -16
-41 -27 56 30
-36 53 -37 77
-36 30 -75 -46
26 -38 -10 62
-32 -54 -6 45
sample output
5hint
樣例解釋: (-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46),(-32, 30, -75, 77), (-32, -54, 56, 30).
暴力做法是列舉abcd中的每個數,四重迴圈,時間複雜度o(n4),太慢。所以我們列舉a+b,構造出乙個n^2大小的陣列並排序,然後再列舉c+d,列舉c和d的時候計算它的相反數在a和b**現多少次(也就是計算乙個數在有序數列中第一次和最後一次出現的位置),即二分查詢左邊界和右邊界。複雜度為o(n2logn2)
若某個-(c+d)在a+b中不存在,則需返回-1,在主函式裡判斷是否返回-1,若是則不能將範圍段加入。
#define _crt_secure_no_warnings
#define _ ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
//#include
#include
#include
#include
using
namespace std;
//快讀
inline
intread()
while
(ch >=
'0'&& ch <=
'9')
x = x *
10+ ch -
'0', ch =
getchar()
;return x * f;
}int a[
4009];
int b[
4009];
int c[
4009];
int d[
4009];
int ab[
16000009];
//a*b
intfind_left
(int x,
int n)
else
if(ab[mid]
> x) r = mid -1;
else l = mid +1;
}return ans;
//返回-1代表不存在
}int
find_right
(int x,
int n)
else
if(ab[mid]
> x) r = mid -1;
else l = mid +1;
}return ans;
//返回-1代表不存在
}int
main()
for(
int i =
0; i < n; i++
)sort
(ab, ab + n * n)
;//對a*b排序
int cur;
int ans=0;
int left, right;
for(
int i =
0; i < n; i++)}
cout << ans;
return0;
}
二分 四個數列
zjm 有四個數列 a,b,c,d,每個數列都有 n 個數字。zjm 從每個數列中各取出乙個數,他想知道有多少種方案使得 4 個數的和為 0。當乙個數列中有多個相同的數字的時候,把它們當做不同的數對待。請你幫幫他吧!第一行 n 代表數列中數字的個數,1 n 4000 接下來的 n 行中,第 i 行有...
week4 二分 四個數列
title zjm 有四個數列 a,b,c,d,每個數列都有 n 個數字。zjm 從每個數列中各取出乙個數,他想知道有多少種方案使得 4 個數的和為 0。當乙個數列中有多個相同的數字的時候,把它們當做不同的數對待。input 第一行 n 代表數列中數字的個數 1 n 4000 接下來的 n 行中,第...
四個數列(二分求解)
小明有四個數列 a,b,c,d,每個數列都有 n 個數字。小明從每個數列中各取出乙個數,他想知道有多少種方案使得 4 個數的和為 0。ps 當乙個數列中有多個相同的數字的時候,把它們當做不同的數對待。input 第一行 n 代表數列中數字的個數 1 n 4000 接下來的 n 行中,第 i 行有四個...