做这道题的时候,首先确定思路,数据量有1600万 ,最大值为2的29次方, 因此,如果纯粹的设标志数组的会爆内存; 然后考虑用哈希来压缩数据量,可以先枚举出两列的和,插入到哈希表中,然后枚举剩余两列; 通过在哈希表里面搜索,即可计数;
代码如下:
#include <stdio.h>
#include <string.h>
#define Max 20000003
int HashTable[Max];//哈希表内容;
int Mark[Max];//标记出现几次数组;
int Mod=Max;//质数;
int data[4005][4];
int Search_Mod(int p)
{//返回模的值;
if(p<0) return (p%Mod+Mod)%Mod;
else return p%Mod;
}
void Inser_data(int p)
{//插入到哈希表里;
int k=Search_Mod(p);
/*
在插入的时候, 截至条件是,mark[k]为0,此时表示k没有被使用,即可;还有就是hashtable[k]=p:
这样就重复
mark[k]++即可;
在跳出循环的话,奋mark[k] 是不是0 ,是0的话就将其插入到新数值里面;
mark[k] 不是0 ,则直接改变mark即可;
*/
while(Mark[k]&&HashTable[k]!=p)
{
k++;//修改冲突, 可以很多情况,
if(k>Mod)k-=Mod;
}
if(!Mark[k])
{
HashTable[k]=p;
Mark[k]=1;
}
else Mark[k]++;//mark不为0 ,说明出现多次;
}
int Find_Key(int p)
{//查找函数,如果mark[k] 为0, 则返回0; 否则继续寻找直到,!Mark[k]||HashTable[k]==p
int k=Search_Mod(p);
while(Mark[k]&&HashTable[k]!=p)
{
k++;
if(k>Mod) k-=Mod;
}
return Mark[k];
}
int main()
{
int n;
long long ans;
while(scanf("%d",&n)!=EOF)
{
for(int i=0;i<n;i++)
for(int j=0;j<4;j++)
scanf("%d",&data[i][j]);
memset(HashTable,0,sizeof(HashTable));
ans=0;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
Inser_data(data[i][0]+data[j][1]);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
ans+=Find_Key(-(data[i][2]+data[j][3]));
printf("%lld\n",ans);
}
}