题意:
给你ABCD四个集合,集合中数的个数都为N(N<=4000),如果分别在ABCD四个集合中取一个数,a b c d ,求有多少种可能使得a+b+c+d=0。
当然你可以尝试枚举所有的组合,绝对可以计算出结果,大概有N^4种吧,如果你有足够的时间还是可以算出来的,哈哈。
当然我不是用上面一种方法计算的,那样算肯定超时。 我的做法是求出所有a+b 到ab数组中, 和所有 c+d到cd数组中,然后排序,枚举每个ab,用二分在cd中查找有没有可能组成0。 有个问题就是二分只能返回一个结果,所以我对二分函数进行了改造,让它返回和要找的值相等的个数。
#include <stdio.h> #include <algorithm> using namespace std; const int N = 4005; int a[N], b[N], c[N], d[N]; int ab[N*N], cd[N*N]; int n, m; int binarysearch(int l, int r, int v) { if (l == r) { int cnt = 0; int lift = l; while (lift >= 0) { if (cd[lift] == v) cnt++; else break; lift--; } int right = l+1; while (right < m) { if (cd[right] == v) cnt++; else break; right++; } return cnt; } int mid = (l+r)>>1; if (v <= cd[mid]) return binarysearch(l, mid, v); else return binarysearch(mid+1, r, v); } int main() { while (scanf("%d", &n) != EOF) { for (int i = 0; i < n; i++) { scanf("%d %d %d %d", &a[i], &b[i], &c[i], &d[i]); } int cnt = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { ab[cnt] = a[i]+b[j]; cd[cnt] = c[i]+d[j]; cnt++; } } int ans = 0; m = n*n; sort(cd, cd+m); for (int i = 0; i < m; i++) { ans += binarysearch(0, m-1, -ab[i]); } printf("%d\n", ans); } return 0; }
poj 2785 4 Values whose Sum is 0(sort+二分)
时间: 2024-11-03 22:41:59