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).
#include <algorithm> #include <cstring> #include <cstdio> #include <iostream> using namespace std; typedef long long LL; typedef unsigned long long ULL; #define MAXN 4100 #define N 3999971 //#define MOD 10000007 //#define INF 1000000009 //const double eps = 1e-9; //const double PI = acos(-1.0); /* Hash a[] +b[]的和打个表 然后分别用c[] + d[]的和查找 */ int a[MAXN], b[MAXN], c[MAXN], d[MAXN]; struct edge { int v, next, cnt; }; edge H[N + 1]; int head[N + 1], k=0; int Hash(int k) { return (k + N) % N; } void add_hash(int val) { int p = Hash(val); for (int i = head[p]; i != -1; i = H[i].next) if (H[i].v == val) { H[i].cnt++; return; } H[k].v = val; H[k].cnt = 1; H[k].next = head[p]; head[p] = k++; } int find_hash(int x) { int p = Hash(x); for (int i = head[p]; i != -1; i = H[i].next) if (H[i].v == x) return H[i].cnt; return 0; } int main() { int n; while (cin>>n) { k = 0; int i, j; LL ans = 0; memset(head, -1, sizeof(head)); for ( i = 0; i < n; i++) cin >> a[i] >> b[i] >> c[i] >> d[i]; for ( i = 0; i < n; i++) for ( j = 0; j < n; j++) add_hash(a[i] + b[j]); for ( i = 0; i < n; i++) for ( j = 0; j < n; j++) ans += find_hash(-c[i] - d[j]); cout << ans << endl; } return 0; }
方法2
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<sstream> #include<algorithm> #include<queue> #include<deque> #include<iomanip> #include<vector> #include<cmath> #include<map> #include<stack> #include<set> #include<fstream> #include<memory> #include<list> #include<string> using namespace std; typedef long long LL; typedef unsigned long long ULL; #define MAXN 4409 #define N 3999971 #define MOD 10000007 #define INF 1000000009 const double eps = 1e-9; const double PI = acos(-1.0); /* */ int a[MAXN], b[MAXN], c[MAXN], d[MAXN], n, l1, l2; vector<int> v1, v2; int cnt(int x) { int beg = 0, end = l2 - 1; while (beg <= end) { int mid = (beg + end) / 2; if (v2[mid] == x) { int cnt = 1; for (int i = mid + 1; i < l2&&v2[i] == x; i++) cnt++; for (int i = mid - 1; i >= 0 && v2[i] == x; i--) cnt++; //cout << x <<"at" << mid<< endl; return cnt; } else if (v2[mid] > x) end = mid - 1; else beg = mid + 1; } return 0; } 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]); for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) v1.push_back(a[i] + b[j]); for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) v2.push_back(-c[i] - d[j]); l1 = v1.size(), l2 = v2.size(); LL ans = 0,pre; sort(v2.begin(), v2.end()); sort(v1.begin(), v1.end()); for (int i = 0; i < l1; i++) { if (i && v1[i] == v1[i - 1]) ans += pre; else pre = cnt(v1[i]), ans += pre; } printf("%lld ", ans); } }