四個數列a、b、c、d,每個數列n個數字,從四個數列中各取乙個數,求共有多少種方案使得4個數和為0。當乙個數列中有多個相同的數字的時候,把它們當做不同的數對待。
第一行:n(代表數列中數字的個數) (1≤n≤4000)
接下來的 n 行中,第 i 行有四個數字,分別表示數列 a,b,c,d 中的第 i 個數(數字不超過 2 的 28 次方)
輸出不同組合的個數。
暴力列舉必然不可取,n<=4000的四重迴圈必然超時,考慮o(n^2)的複雜度演算法,因為a+b+c+d=0相當於a+b=-(c+d),可以使用二分。
首先列舉ab數列的所有和,再列舉cd數列的和,在列舉cd和時,通過二分找到其相反數在ab數列和中第一次出現和最後一次出現的位置,由此可以統計出每組a+b=-(c+d)個個數,最後輸出總個數即可。
#include
#include
using
namespace std;
int a[
4010
],b[
4010
],c[
4010
],d[
4010];
int ab_sum[
16000010];
intfind_first
(int x,
int l,
int r)
else
if(x>ab_sum[mid]
) l=mid+1;
else
r=mid-1;
}return ans;
}int
find_last
(int x,
int l,
int r)
else
if(x>ab_sum[mid]
) l=mid+1;
else
r=mid-1;
}return ans;
}int
main()
}sort
(ab_sum,ab_sum+m+1)
;for
(int i=
0;i++i)
} cout
}
本題是一道二分的題目,利用二分可以找到一組數中第乙個(最後乙個)比給定數字大或小的數,利用這種形式,我們可以很方便的找到滿足某種條件的數字或表示式的個數,帶入到本題當中,常規的四重迴圈o(n^4)複雜度顯然是不能接受的,而簡單變換形式之後,就可以使用二分的思想進行求解,大大優化了程式執行的時間。 week4 B 四個數列
zjm 有四個數列 a,b,c,d,每個數列都有 n 個數字。zjm 從每個數列中各取出乙個數,他想知道有多少種方案使得 4 個數的和為 0。當乙個數列中有多個相同的數字的時候,把它們當做不同的數對待。input 第一行 n 代表數列中數字的個數 1 n 4000 接下來的 n 行中,第 i 行有四...
week4 B 四個數列
zjm 有四個數列 a,b,c,d,每個數列都有 n 個數字。zjm 從每個數列中各取出乙個數,他想知道有多少種方案使得 4 個數的和為 0。當乙個數列中有多個相同的數字的時候,把它們當做不同的數對待。請你幫幫他吧!輸入輸出格式input 第一行 n 代表數列中數字的個數 1 n 4000 接下來的...
Week4 B 四個數列
zjm 有四個數列 a,b,c,d,每個數列都有 n 個數字。zjm 從每個數列中各取出乙個數,他想知道有多少種方案使得 4 個數的和為 0。當乙個數列中有多個相同的數字的時候,把它們當做不同的數對待。第一行 n 代表數列中數字的個數 1 n 4000 接下來的 n 行中,第 i 行有四個數字,分別...