給定4個組合A,B,C,D,這四個組合裏面的元素數目相等。要求找出所有的序列(a, b, c, d),四個數分別來自A,B,C,D四個組合,使得a + b + c + d = 0,輸出這樣的序列的總數。若兩個滿足條件的序列是完全相同的,它們也算是不同的序列,因爲A,B,C,D中可能含有相同的元素。
解題思路很簡單,取所有的(a, b)序列進行哈希,以a+b作爲鍵,分別映射到非負數和負數兩個哈希表上,若有重複的(a, b),則只需要記錄次數,不需要再開闢結點存儲。
然後對所有的(c, d)序列,以c+d作爲鍵進行查找,若c+d爲正則查找對應的負數哈希表,若爲負則查找對應的非負數哈希表,把符合a+b+c+d=0的所有結點的所有次數相加就得到最後的答案了。
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 9000005;
const int M = 4005;
const int H = 4000007;
int n;
long long ans;
int A[M], B[M], C[M], D[M];
struct Node
{
int a;
int b;
int cnt;
int next;
};
Node nodeP[N];
Node nodeN[N];
int curP, curN;
int hashTableP[H];
int hashTableN[H];
void initHash()
{
for (int i = 0; i < H; ++i) hashTableP[i] = hashTableN[i] = -1;
curP = curN = 0;
ans = 0;
}
void searchHash(int& a, int& b)
{
int h = (a + b) % H;
int next;
if (h >= 0)
{
next = hashTableP[h];
while (next != -1)
{
if (a == nodeP[next].a && b == nodeP[next].b)
{
++nodeP[next].cnt;
return;
}
next = nodeP[next].next;
}
nodeP[curP].a = a;
nodeP[curP].b = b;
nodeP[curP].cnt = 1;
nodeP[curP].next = hashTableP[h];
hashTableP[h] = curP;
++curP;
}
else
{
h = -h;
next = hashTableN[h];
while (next != -1)
{
if (a == nodeN[next].a && b == nodeN[next].b)
{
++nodeN[next].cnt;
return;
}
next = nodeN[next].next;
}
nodeN[curN].a = a;
nodeN[curN].b = b;
nodeN[curN].cnt = 1;
nodeN[curN].next = hashTableN[h];
hashTableN[h] = curN;
++curN;
}
}
void getAns(int& c, int& d)
{
int h = (c + d) % H;
int next;
if (h > 0)
{
next = hashTableN[h];
while (next != -1)
{
if (nodeN[next].a + nodeN[next].b + c + d == 0) ans += nodeN[next].cnt;
next = nodeN[next].next;
}
}
else
{
h = -h;
next = hashTableP[h];
while (next != -1)
{
if (nodeP[next].a + nodeP[next].b + c + d == 0) ans += nodeP[next].cnt;
next = nodeP[next].next;
}
}
}
int main()
{
initHash();
scanf("%d", &n);
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)
{
searchHash(A[i], B[j]);
}
}
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n; ++j)
{
getAns(C[i], D[j]);
}
}
printf("%lld\n", ans);
return 0;
}