The SUM problem can be formulated as follows: given four lists A,B,C,D of integer values, compute how many quadruplet (a,b,c,d) ∈ A×B×C×D are such that a+b+c+d = 0. In the following, we assume that all lists have the same size n.
Input
The input begins with a single positive integer on a line by itself indicating the number of the cases following, each of them as described below. This line is followed by a blank line, and there is also a blank line between two consecutive inputs.
The first line of the input file contains the size of the lists n (this value can be as large as 4000). We then have n lines containing four integer values (with absolute value as large as 228) that belong respectively to A,B,C and D.
Output
For each test case, your program has to write the number quadruplets whose sum is zero. The outputs of two consecutive cases will be separated by a blank line.
Sample Input
1
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
5
Sample Explanation: Indeed, the sum of the five following quadruplets is zero: (-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46), (-32, 30, -75, 77), (-32, -54, 56, 30).
Input
The input begins with a single positive integer on a line by itself indicating the number of the cases following, each of them as described below. This line is followed by a blank line, and there is also a blank line between two consecutive inputs.
The first line of the input file contains the size of the lists n (this value can be as large as 4000). We then have n lines containing four integer values (with absolute value as large as 228) that belong respectively to A,B,C and D.
Output
For each test case, your program has to write the number quadruplets whose sum is zero. The outputs of two consecutive cases will be separated by a blank line.
Sample Input
1
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
5
Sample Explanation: Indeed, the sum of the five following quadruplets is zero: (-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46), (-32, 30, -75, 77), (-32, -54, 56, 30).
#include <algorithm>
#include <iostream>
#include<cmath>
#include<cstring>
#include<stdio.h>
#define maxn 4005
#define MAX 200000000
using namespace std;
/*
题目大意:给定四列数和其行数,让找出满足和为零的四元组的个数,
其中四元组满足每个数都在不同 的列数中。
对每两列进行两重循环枚举出所有和的情况并用整数栈记录,
然后排序,对另外两列枚举出的每个结果,在有序数组中进行二分查找,
总体复杂度为O(n^2logn),当然也要注意常数阶级,由于暂时不会哈希,
所以直接二分。
注意:对每个数的二分不是找这个数,而是找这个数的区间,
至于二分找区间问题,我们知道二分可以找左上界和右下界,但是混在一起用就不妥,
因为会有边界值的问题,这时借鉴他人之玉,,先搞出下界,
再循环暴力出所有个数(汗。。不知道会不会超时)
*/
long long seq[4][maxn];
long long tmp[MAX],cnt;
bool binary(long long x)
{
int l=0,r=cnt-1;
while(l<=r)
{
int mid=(l+r)/2;
if(tmp[mid]>x) r=mid-1;
else if (tmp[mid]<x) l=mid+1;
else {
//cout<<x<<endl;
return true;
}
}
return false;
}
int main()
{
int t;cin>>t;
for(int tt=0;tt<t;tt++)
{
if(tt)
puts("");
int n;cin>>n;
for(int j=0;j<n;j++) cin>>seq[0][j]>>seq[1][j]>>seq[2][j]>>seq[3][j];
cnt=0;
long long ans=0;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
tmp[cnt++]=( seq[0][i]+seq[1][j] );
sort(tmp,tmp+cnt);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
int l=0,r=cnt-1,mid;
while(l<r)
{
mid=(l+r)>>1;
if( tmp[mid] < -seq[2][i]-seq[3][j] )
l=mid+1;
else
r=mid;
}
while( l<cnt && tmp[l]==-seq[2][i]-seq[3][j] )
{
ans++;l++;
}
}
printf("%lld\n",ans);
}
return 0;
}