POJ2785 和为0的组合数(数的哈希)

来源:互联网 发布:软件缺陷报告模板 编辑:程序博客网 时间:2024/05/17 19:20

给定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;}


原创粉丝点击