时间限制: 1 Sec 内存限制: 512 MB
题目描述
给定4个n元素集合A,B,C,D,要求分别从中选取一个元素a, b, c, d,使得a + b + c + d = 0
问:有多少种选法
输入
第1行:1个整数表示测试数据的组数,然后一个空行
第3行:1个整数n,表示每个集合有多少个元素
接下来n行,每行4个整数,绝对值不超过2^28,分别表示A,B,C,D四个集合中的一个元素
输出
对每组测试数据输出一行,1个整数,表示答案
样例输入
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
样例输出
5
思路
首先,dfs什么的都是肯定会超时的。
然后,我们可以发现两倍上限是不会超时的。
于是,可以用一个数组来存当前有哪些数(a+b),
然后直接在c+d中判断相反数就可以了。
#include<map>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=4005;
int K,ans,n,p,l,r,mid;
int a[MAXN],b[MAXN];
int c[MAXN],d[MAXN];
int o[MAXN*MAXN];
int main()
{
scanf("%d",&K);
while(K--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
o[++p]=a[i]+b[j];
sort(o+1,o+p+1);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
ans+=upper_bound(o+1,o+p+1,-c[i]-d[j])-lower_bound(o+1,o+p+1,-c[i]-d[j]);
printf("%d\n",ans);
for(int i=0;i<=n+1;i++)
a[i]=b[i]=c[i]=d[i]=0;
for(int i=0;i<=p+1;i++)
o[i]=0;
ans=p=0;
if(K)puts("");
}
}