4 Values whose Sum is 0
Time Limit: 15000MS |
|
Memory Limit: 228000K |
Total Submissions: 6014 |
|
Accepted: 1456 |
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
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).
Source
Southwestern Europe 2005
偶用2分过了以后又用HASH过了次,发现HASH就是快- -!
2分5000MS+,HASH 3000MS+
差距啊。。。
2分就是先把1,2两列的和先算出来,然后再把3,4两列的和也算出来,最后二分查找得到一个解,注意解的附近也可能有解存在!
HASH的时候开静态数会很快~偶用的是最土的取MOD完接表。
下面是2分代码:
- #include<iostream>
- #include<algorithm>
- using namespace std;
- #define N 4000
- #define M 16000000
- int a[N],b[N],c[N],d[N],ab[M],cd[M];
- int main()
- {
- int n,i,j,k,l,r,mid,cnt,ablen,cdlen;
- while(scanf("%d",&n)!=EOF)
- {
- cnt=ablen=cdlen=0;
- for(i=0;i<n;i++)
- {
- scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
- }
- for(i=0;i<n;i++)
- for(j=0;j<n;j++)
- ab[ablen++]=a[i]+b[j];
- for(i=0;i<n;i++)
- for(j=0;j<n;j++)
- cd[cdlen++]=-c[i]-d[j];
- sort(cd,cd+cdlen);
- for(i=0;i<ablen;i++)
- {
- l=0;
- r=cdlen-1;
- while(l<=r)
- {
- mid=(l+r)/2;
- if(cd[mid]==ab[i])
- {
- cnt++;
- for(k=mid+1;k<cdlen;k++)
- if(cd[k]!=ab[i])break;
- else cnt++;
- for(k=mid-1;k>=0;k--)
- if(cd[k]!=ab[i])break;
- else cnt++;
- break;
- }
- if(cd[mid]<ab[i])
- l=mid+1;
- else r=mid-1;
- }
- }
- printf("%d/n",cnt);
- }
- return 0;
- }
之后的HASH写的就比较顺利,有了ZX大牛的指点,1次AC,效率比他还高- -!!
- #include<iostream>
- using namespace std;
- #define N 4000
- #define M 17100000
- const int p=1048576;
- struct Node
- {
- int val,cnt,next;
- };
- Node hash[M];
- bool flag[M];
- int a[N][4],hlen=p,cnt=0;
- inline int gn()
- {
- char buf=getchar();
- int sgn=(buf=='-'?-1:1),ret=0;
- if(buf!='-')ungetc(buf,stdin);
- while((buf=getchar())!=' '&&buf!='/n')
- ret=ret*10+(buf-48);
- return ret*sgn;
- }
- void ins(int val,int key)
- {
- if(!flag[key])
- {
- flag[key]=true;
- hash[key].cnt=1;
- hash[key].val=val;
- hash[key].next=-1;
- return;
- }
- while(key!=-1)
- {
- if(val==hash[key].val)
- {
- hash[key].cnt++;
- return;
- }
- if(hash[key].next==-1)break;
- key=hash[key].next;
- }
- hash[key].next=++hlen;
- hash[hlen].val=val;
- hash[hlen].cnt=1;
- hash[hlen].next=-1;
- }
- void fnd(int val,int key)
- {
- if(!flag[key])
- return;
- while(key!=-1)
- {
- if(val==hash[key].val)
- {
- cnt+=hash[key].cnt;
- return;
- }
- key=hash[key].next;
- }
- }
- int main()
- {
- int n,i,j,tmp;
- bool nag;
- n=gn();
- for(i=0;i<n;i++)
- for(j=0;j<4;j++)
- a[i][j]=gn();
- for(i=0;i<n;i++)
- for(j=0;j<n;j++)
- {
- tmp=a[i][0]+a[j][1];
- nag=tmp<0;
- if(nag)tmp*=-1;
- ins(a[i][0]+a[j][1],tmp&(p-1));
- }
- for(i=0;i<n;i++)
- for(j=0;j<n;j++)
- {
- tmp=-a[i][2]-a[j][3];
- nag=tmp<0;
- if(nag)tmp*=-1;
- fnd(-a[i][2]-a[j][3],tmp&(p-1));
- }
- printf("%d/n",cnt);
- return 0;
- }