将数据2分,对一半求出n*n个和,hash存到一个容器。
对另一半也求出n*n个和,到hash容器中查找一下就ok了,很容易得到sum=0的情况总数。
用&运算: #define hash(x) ( (x) & H)耗时2000ms, 如果是#define hash(x) ( (x) % H)就TLE。。。
//poj 2785
//G++ AC C++ AC
const int S=4005;
const int H=16777215; //(x&(2^n-壹)) 16777215
#define hash(x) ( (x) & H) //(x&(2^n-壹)) 16777215
#include <stdio.h>
#include <string.h>
#include <cstdlib>
#include <ctime>
#include <cmath>
using namespace std;
int a1[H+20000];
int a2[H+20000];
void initHash() {
memset(a1, 255, sizeof(a1));
}
inline int gen(int x) { //如果存在,则返回此元素下标;如果不存在,则新建,并且返回下标
if (x==-1) return H+1;
int z = hash(x);
while(a1[z]!=-1 && a1[z]!=x) z = hash(z+1);
if(a1[z] == -1) a1[z]=x, a2[z]=0;
return z;
}
inline int get(int x) { //如果存在,则返回此元素下标;如果不存在,则返回-1
if (x==-1) return H+1;
int z = hash(x);
while(a1[z]!=-1 && a1[z]!=x) z=hash(z+1);
if(a1[z]==-1) return -1;
return z;
}
int g[S][4];
int main(){
int n,i,x,j,sum=0,k;
initHash();
// a2[gen(-1)]=3;
// a2[gen( 2)]=5;
// printf("a[-1]=%d\n",a2[get(-1)]);
// printf("a[2]=%d\n",a2[get(2)]);
scanf("%d",&n);
for (i=0;i<n;i++)
for (j=0;j<4;j++)
scanf("%d",&g[i][j]);
// g[i][j]=rand()*(0x3FFF-rand());
for (i=0;i<n;i++)
for (j=0;j<n;j++)
{
x=g[i][0]+g[j][1];
k=gen(x);
a2[k]++;
// printf("k1=%d\n",k);
}
for (i=0;i<n;i++)
for (j=0;j<n;j++)
{
x=g[i][2]+g[j][3];
k=get(0-x);
if (k>=0) sum+=a2[k];
// printf("k2=%d\n",k);
}
printf("%d\n",sum);
return 0;
}