题目大意:给出一个整数n,接下来有n组数,每组数包含四个数 a、b、c、d 求有多少中组合方式使得 a+b+c+d = 0
题目数据范围 n <= 4000, 强行枚举的话,一共有4000^4种方式。这是必不可行的。
我们来引入一下折半枚举的思想:
当枚举的集合过大导致无法简单实现,同时刚好只需要他们的和或其他可以处理出的东西,就可以一半一半的枚举搜索。
在本题当中:
a + b + c + d = 0 >> (a + b) = -(c + d) 而对于 a + b 和 c + d 都分别有4000^2 种情况,可以枚举出来。这时就可以利用折半枚举。
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 4005;
ll n, ans;
ll a[N], b[N], c[N], d[N], f[N*N];
int main(){
scanf("%lld", &n);
for(int i = 1; i <= n; i++)
scanf("%lld%lld%lld%lld", &a[i], &b[i], &c[i], &d[i]);
ll cnt = 1;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
f[cnt++] = c[i] + d[j];
}
}//枚举c + d 并保存起来
sort(f+1, f+cnt);
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
ll temp = -(a[i] + b[j]);//枚举a+b
ans += upper_bound(f+1, f+n*n+1, temp) - lower_bound(f+1, f+n*n+1, temp);
//同时找出有多少组c+d满足情况
}
}
printf("%lld\n", ans);
return 0;
}