Description
给出四个数列,现从每个数列中选取一个数,问有多少中可能使这四个数和为0
Input
第一行为数列长度,之后n行每行4个整数分别表示四个数列中对应位置的值
Output
输出4个数和为0的可能数
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
5
Solution
用前两列的和维护一个hash,然后用第三第四列的和的相反数去hash里面找即可
Code
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<functional>
#include<queue>
using namespace std;
#define maxn 4001
int n;
int a[maxn],b[maxn],c[maxn],d[maxn];
int cd[maxn*maxn];
int cmp(const void*a,const void*b)
{
return *(int*)a-*(int*)b;
}
int main()
{
scanf("%d",&n);
int i,j;
for(i=0;i<n;i++)
scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
for(i=0;i<n;i++)//用前两列的和维护hash表
for(j=0;j<n;j++)
cd[i*n+j]=c[i]+d[j];
qsort(cd,n*n,sizeof(int),cmp);//对hash表排序
long long res=0;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
int t=-(a[i]+b[j]);//在hash表中查找三四列和的相反数
res+=upper_bound(cd,cd+n*n,t)-lower_bound(cd,cd+n*n,t);
}
printf("%lld\n",res);
return 0;
}