前言
这是道英文题哦,做之前请先打开翻译软件。
题目描述
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 2^28) that belongrespectively 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).
题意
有4个数组,让你从每个数组里找一个数,使得它们的和为0
解析
初想的时候,大家应该和我一样,感觉这道题不难。
既不用什么DP,又不用什么二分(更不可能是图论了),不就是个DFS吗。
但是请看数据规模
别人数据有4000行!
那没办法了。
办法还是有的,那就是折半搜索。
我们把四个数组分成两组
对于前两组,我们挨着枚举,并把他们的和作为下标,方案数作为值存在map里。
对于后两组,我们照样挨着枚举,只要map里有他们的存在,就把ans加上一个相应的值.
代码
这道题因为数据比较大,所以单纯的map会超时,要用哈希
#include<set>
#include<cmath>
#include<cstdio>
#include<vector>
using namespace std;
#define MAXN 9999991
vector < pair<int,int> > Hash[MAXN+5];
vector <int> a,b,c,d;
int HashAlgorithm(int x){
return (x%MAXN+MAXN)%MAXN;
}
void Push(int w,int val){
for(int i=0;i<Hash[w].size();i++)
if(Hash[w][i].first==val){
Hash[w][i].second++;
return;
}
Hash[w].push_back(make_pair(val,1));
}
int main(){
//freopen("data.txt","r",stdin);
int T;
bool fir=false;
scanf("%d",&T);
while(T--){
getchar();
int n,ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++){
int a1,b1,c1,d1;
scanf("%d %d %d %d",&a1,&b1,&c1,&d1);
a.push_back(a1);b.push_back(b1);c.push_back(c1);d.push_back(d1);
}
for(int i=0;i<c.size();i++)
for(int j=0;j<d.size();j++){
int x=HashAlgorithm(c[i]+d[j]);
Push(x,c[i]+d[j]);
}
for(int i=0;i<a.size();i++)
for(int j=0;j<b.size();j++){
int k1=HashAlgorithm(0-a[i]-b[j]);
for(int k=0;k<Hash[k1].size();k++)
if(Hash[k1][k].first==(0-a[i]-b[j])){
ans+=Hash[k1][k].second;
break;
}
}
if(fir) puts("");
else fir=true;
printf("%d\n",ans);
for(int i=0;i<=MAXN;i++)
Hash[i].clear();
a.clear();b.clear();c.clear();d.clear();
}
}