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 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).
(是不是先得翻译 )题意大概是给定四个长度为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;
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 }