UVa 1152 - 4 Values whose Sum is 0

链接:

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3593

 

题意:

给定4个n(1≤n≤4000)元素集合A, B, C, D,要求分别从中选取一个元素a, b, c, d,使得a+b+c+d=0。问:有多少种选法?

 

分析:

折半枚举 + 散列表

首先枚举c和d,把所有-c-d记录下来放在散列表里,然后枚举a和b,查一查a+b有多少种方法写成-c-d的形式。

 

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 
 5 const int UP_HASH = 1000000;
 6 
 7 struct NODE {
 8     int val, num, next;
 9 } node[UP_HASH * 10];
10 
11 int np, head[UP_HASH], a[4][4000+5];
12 
13 inline int cor(int n){
14     return abs(n) % (UP_HASH - 5) + 1;
15 }
16 
17 int amount(int v){
18     int h = cor(v);
19     int i = head[h];
20     while(i){
21         if(node[i].val == v) return node[i].num;
22         i = node[i].next;
23     }
24     return 0;
25 }
26 
27 void add(int v){
28     int h = cor(v);
29     int i = head[h];
30     while(i){
31         if(node[i].val == v){
32             node[i].num++;
33             return;
34         }
35         i = node[i].next;
36     }
37     node[np].val = v;
38     node[np].num = 1;
39     node[np].next = head[h];
40     head[h] = np++;
41 }
42 
43 int main(){
44     int T, n;
45     scanf("%d", &T);
46     while(T--){
47         scanf("%d", &n);
48         for(int i = 0; i < n; i++){
49             scanf("%d%d%d%d", &a[0][i], &a[1][i], &a[2][i], &a[3][i]);
50         }
51         np = 1;
52         memset(head, 0, sizeof(head));
53         for(int t = 0; t < n; t++){
54             for(int i = 0; i < n; i++) add(-a[2][t] - a[3][i]);
55         }
56         int ans = 0;
57         for(int t = 0; t < n; t++){
58             for(int i = 0; i < n; i++) ans += amount(a[0][t] + a[1][i]);
59         }
60         printf("%d\n", ans);
61         if(T) printf("\n");
62     }
63     return 0;
64 }

 

posted @ 2017-12-16 17:26  Ctfes  阅读(138)  评论(0编辑  收藏  举报