http://poj.org/problem?id=2785
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).
题目大意:给你四个数组,(第一列为第一个数组……)让你从这四个数组中各找一个元素,使他们之和等于0。问你有多少种情况。
思路:设四个数组分别为a、b、c、d,新开辟两个数组ab、cd,预处理数组a和数组b得到所有可能的和存储在数组ab中,(即从数组a选一个元素 数组b选一个元素 加起来存储到ab中),对c、d做同样的操作,只不过把他们的和的相反数存储到cd中。那么问题就转化为从ab数组中找一个元素X,从cd数组中找一个元素Y,使X=Y。对ab、cd排序后使用二分即可。时间复杂度应该是n^2lgn吧,常数比较大,不过题目给了15秒,够用了。题目求的是方案数,仔细思考应该就知道cnt为什么那么写了。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<set>
#include<algorithm>
#include<iterator>
#define INF 0x3f3f3f3f
using namespace std;
int a[4000];
int b[4000];
int c[4000];
int d[4000];
int ab[4000*4000];
int cd[4000*4000];
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;++i)
scanf("%d %d %d %d",&a[i],&b[i],&c[i],&d[i]);
int k1=0,k2=0;
for(int i=0;i<n;++i)
{
for(int j=0;j<n;++j)
{
ab[k1++]=a[i]+b[j];
cd[k2++]=-(c[i]+d[j]);
}
}
sort(ab,ab+k1);
sort(cd,cd+k2);
int cur=ab[0];
int t1,t2,t3,t4;
long long cnt=0;
while(1)
{
t1=lower_bound(ab,ab+k1,cur)-ab;
t2=upper_bound(ab,ab+k1,cur)-ab;
t3=lower_bound(cd,cd+k2,cur)-cd;
t4=upper_bound(cd,cd+k2,cur)-cd;
cnt+=(long long)(t4-t3)*(t2-t1);
if(t2!=k1)
cur=ab[t2];
else
break;
}
printf("%lld\n",cnt);
return 0;
}