一、題目描述
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 input6-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 output5
hint二、思路概述樣例解釋: (-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46),(-32, 30, -75, 77), (-32, -54, 56, 30).
1.考慮到如果列舉四個數列中的元素,計算每一次的和,再看共有多少個和是0,但是這種暴力列舉的方法複雜度太高,必須要找到乙個複雜度比較低的方法。
2.將a、b陣列中的元素的和列舉出來,放在乙個陣列ab裡,c、d的放在另乙個陣列cd裡,並將陣列cd進行排序。
3.然後遍歷陣列ab,每次在陣列cd中查詢ab元素的相反數有幾個。最後查詢出來的相反數的數量和就是我們要求的答案。
三、注意點(錯過的地方)
1.我計算ab中元素的相反數個數的方法是:對陣列cd進行二分查詢,找到相反數出現的最後乙個位置,和出現的第乙個位置,他們的差+1,就是相反數的個數。而最初的我沒有加上這個1,就出錯了。
四、新的函式用法
1.二分法是一種非常有效且快速的查詢方法,可以應用於很多的地方,但是使用的時候要靈活應用。
五、完整**
#include
#include
using
namespace std;
int n;
intfind1
(int x,
int*cd)
//找到x在陣列的第乙個位置
else
if(cd[mid]
>x)r=mid-1;
else l=mid+1;
}return ans;
}int
find2
(int x,
int*cd)
//找到x在陣列的最後乙個位置
else
if(cd[mid]
>x)r=mid-1;
else l=mid+1;
}return ans;
}void
csum
(int
*ab,
int*cd)
} cout<}int
main()
二分 四個數列
zjm 有四個數列 a,b,c,d,每個數列都有 n 個數字。zjm 從每個數列中各取出乙個數,他想知道有多少種方案使得 4 個數的和為 0。當乙個數列中有多個相同的數字的時候,把它們當做不同的數對待。請你幫幫他吧!第一行 n 代表數列中數字的個數,1 n 4000 接下來的 n 行中,第 i 行有...
B 4個數列 二分法
zjm 有四個數列 a,b,c,d,每個數列都有 n 個數字。zjm 從每個數列中各取出乙個數,他想知道有多少種方案使得 4 個數的和為 0。對於四個數列之和,最暴力的想法就是列舉四個數列的數,那樣時間複雜度是o n 4 顯然複雜度太高了。我們的思路是,計算a b的和 o n n 存放在陣列a裡面 ...
四個數列(二分求解)
小明有四個數列 a,b,c,d,每個數列都有 n 個數字。小明從每個數列中各取出乙個數,他想知道有多少種方案使得 4 個數的和為 0。ps 當乙個數列中有多個相同的數字的時候,把它們當做不同的數對待。input 第一行 n 代表數列中數字的個數 1 n 4000 接下來的 n 行中,第 i 行有四個...