[poj2785]4 Values whose Sum is 0(hash或二分)

4 Values whose Sum is 0

Time Limit: 15000MS Memory Limit: 228000K
Total Submissions: 19322 Accepted: 5778
Case Time Limit: 5000MS

Description

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 228 ) 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).

(是不是先得翻译 )题意大概是给定四个长度为n的数组,求四个数组各取一个元素和为0的取法有几种(考虑顺序)

首先有两种做法,一种二分,一种哈希

看一眼数据规模知道枚举每一位的O(n^4)绝对超时

所以观察题目,发现只要求和为0,那么考虑只枚举出前两个数组的任意元素和与后两个数组任意元素和

这样再枚举一遍前两个数组的任意元素和,检查是否有对应元素和为0即可

接下来还要再优化

二分写得很简单,具体代码在《挑战程序设计竞赛》第23页不想写

再来看哈希

把两数组的元素和得出一个键值(就是哈希值)接下来链式储存进去

什么叫链式呢?就是和邻接表差不多

把哈希映射的数组当成head数组,把原值当成边,存原值和next也就是哈希值相同的下一个值的为止

注意这道题还得再优化,多存一个同一数值的重复次数而不是分开存,不然会MLE没错这是省空间用的

1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<string.h>
 4 const int mod=1000007;
 5 typedef struct{
 6         int val;
 7         int num;
 8         int next;
 9 }node;
10 int data[4005][4];
11 int n,tot=0;
12 int hash[mod+1];
13 node all[16000000];
14 int abs(int num){
15     return num>0?num:(-1)*num;//考虑负数!考虑负数!考虑负数!
16 }
17 int get(int num){
18     return (abs(num))%mod;
19 }
20 int add(int num){
21     int tmp=get(num);
22     int p=1;
23     if(hash[tmp]){
24        for(p=hash[tmp];p!=0;p=all[p].next){
25            if(all[p].val==num){
26               all[p].num++;
27               break;
28            }
29        }
30     }
31     if((!hash[tmp])||(p==0)){
32           all[++tot].val=num;
33           all[tot].num=1;
34           all[tot].next=hash[tmp];
35           hash[tmp]=tot;
36     }
37     return 0;
38 }
39 int find(int num){
40     int tmp=get(num);
41     int p;
42     for(p=hash[tmp];p;p=all[p].next){
43         if(all[p].val==num)return all[p].num;
44     }
45     return 0;
46 }
47 int main(){
48     memset(hash,0,sizeof(hash));
49     memset(all,0,sizeof(all));
50     int n;
51     scanf("%d",&n);
52     for(int i=1;i<=n;i++)scanf("%d %d %d %d",&data[i][1],&data[i][2],&data[i][3],&data[i][4]);
53     for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)add(data[i][1]+data[j][2]);
54     int ans=0;
55     for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)ans+=find(-(data[i][3]+data[j][4]));
56     printf("%d",ans);
57     return 0;

58 }

时间: 2024-11-14 16:47:14

[poj2785]4 Values whose Sum is 0(hash或二分)的相关文章

poj 2785 4 Values whose Sum is 0(sort+二分)

题意: 给你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.  有个问题就是二分只能返回一个结果,所以

poj 2785 4 Values whose Sum is 0 (简单二分)

//每列选一个数相加为0的个数 # include <stdio.h> # include <algorithm> # include <string.h> using namespace std; int ab[4010*4010],cd[4010*4010]; int main() { int n,i,k,j,count,a[4010],b[4010],c[4010],d[4010]; while(~scanf("%d",&n)) { f

POJ2785 4 Values whose Sum is 0 【枚举】

4 Values whose Sum is 0 Time Limit: 15000MS   Memory Limit: 228000K Total Submissions: 16000   Accepted: 4625 Case Time Limit: 5000MS Description The SUM problem can be formulated as follows: given four lists A, B, C, D of integer values, compute how

POJ-2785 4 Values whose Sum is 0(折半枚举 sort + 二分)

题目链接:http://poj.org/problem?id=2785 题意是给你4个数列.要从每个数列中各取一个数,使得四个数的sum为0,求出这样的组合的情况个数. 其中一个数列有多个相同的数字时,把他们看作不同的数字. 做法是把前两个数列和的值存在一个数组(A)中 , 后两个数列的和存在另一个数组(B)中 , 数组都为n^2 . 然后将B数组sort一下 , 将A数组遍历 , 二分查找一下B数组中与A数组元素和为0的个数 . 有个注意的点是万一A数组都是0 , 而B数组都为0的情况(还有其

uva1152 - 4 Values whose Sum is 0(hash或STL技巧ac)

题目大意:给定4个n(1 <= n <= 4000)元素集合A, B, C, D,要求分别从中选取一个元素a, b, c, d,使得a+b+c+d = 0,问有多少种选法. method 1: 这里用到一个很实用的技巧: 求长度为n的有序数组a中的数k的个数num? num=upper_bound(a,a+n,k)-lower_bound(a,a+n,k); #include <iostream> #include <cstring> #include <algo

UVa1152 - 4 Values whose Sum is 0(hash)

hash结构体 struct Hash_map { static const int mask=0x7fffff; int p[8388608],q[8388608]; void clear(){ for(int i=0;i<=mask;++i) q[i]=0; } int & operator [] (int k){ int i; for(i=k&mask; q[i]&&p[i]!=k; i=(i+1)&mask); p[i]=k; return q[i];

POJ2785 4 Values whose Sum is 0(二分)

题目链接: http://poj.org/problem?id=2785 题意: 给定你四个大小为n的集合 然后又多少个四元组的和为0,分别来自这四个集合: 分析: 分成两组,得到sum1[[,sum2[],然后排下序,在sum2中二分搜索-sum1[i]记下数就可以了 代码如下: #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using names

POJ2785:4 Values whose Sum is 0(二分)

Description 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 s

1152 - 4 Values whose Sum is 0(好用的hash标记,多重循环简单化)

不得不说这个题就是炫酷啊! 首先说一说思路吧,是这么想的: 1.弄四重循环,爆破,明显会超时. 2.为了处理多重循环,就枚举a+b+c,只需要在d中找到a+b+c的相反数即可,超时 3.枚举a+b,只需要在c+d中找到a+b的相反数即可,TMD超时! 4.循环只能优化到这个程度了,再优化就得用哈希表直接调用了. 这个题的哈希表也是新的知识,由于本题a+b的值可能很大很大,所以以前的哈希表检索不好用了(因为数组开不了那么大),多亏高神的Blog,学了一招,哈哈,下面是搬运的内容: 对于一个无法用数