TOJ 2407 4 Values whose Sum is 0 哈希算法

做这道题的时候,首先确定思路,数据量有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);
    }
}


你可能感兴趣的:(HashCode,TOJ)