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 x B x C x D are such that a + b + c + d = 0 . In the following, we assume that all lists have the same size n .
Input
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 2 28 ) that belong respectively to A, B, C and D .
Output
For each input file, your program has to write the number quadruplets whose sum is zero.
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
Hint
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).
大致题意:给你四列数,让你从每一列中选一个数,使得4个数的和为0,问有多少种方案
思路:如果直接暴力枚举的话n^4肯定是会超时的,所以我们折半枚举,先暴力枚举出其中前两列的所有和,存到一个数组中,排个序。然后再枚举后两列的和,利用lower_bound可以快速找到所需对应的前两列的结果,时间复杂度差不多就降到了n^2.
代码如下
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#define ll long long
using namespace std;
ll s1[4005];
ll s2[4005];
ll s3[4005];
ll s4[4005];
ll sum1[16000005];
ll sum2[16000005];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld%lld%lld%lld",&s1[i],&s2[i],&s3[i],&s4[i]);
}
int l=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
sum1[l++]=s1[i]+s2[j];
}
sort(sum1,sum1+n*n);
ll sum=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
ll x=s3[i]+s4[j];
x=-x;
int tmp1=lower_bound(sum1,sum1+n*n,x)-sum1;//返回a[]中第一个大于等于val的位置
int num=0;
for(int k=tmp1;k<n*n;k++)//相同的值可能有多个
{
if(sum1[k]==x)
{
sum++;
}
else
break;
}
}
printf("%lld",sum);
return 0;
}