这两天看文章,看得手又痒了。于是提前开了自己挂的hash专题。因为在数据结构课上有学过,所以大致思路还记得。看了下网上的解法和细节上的东西,差不多就能写一些简单题了。
这题用的是线性探测除法散列法,要注意的是key = (num % mod + mod) % mod。前面的%mod是为了防止出现比mod大的数,再加mod是为了解决负数的问题。
这题其实也可以用n^2+二分,但是题目给的内存很大,标程估计也是要用哈希的意思。
从virtual oj的提交记录来看,基本二分的都在5000+MS,有一个hash的做法竟然用了10000+MS,看了下代码,可能是指针的关系?
最后提交的代码是3000+MS过的。
思路就是:用前两列的和维护一个hash,然后用第三第四列的和的相反数去hash里面找即可。
Code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int mod = 15999991;
int hash[16000011]; //hash table
int cnt[16000011]; // time of the each hash relationship
int a[4444][4];
int n;
void make_hash(int num)
{
int key = (num % mod + mod) % mod; //division hash
while((hash[key] != num) && (cnt[key] > 0)) key = (key + 1) % mod; //linear detect
hash[key] = num;
cnt[key] ++;
}
int get_num(int num)
{
int key = (num % mod + mod) % mod;
while((hash[key] != num) && (cnt[key] > 0)) key = (key + 1) % mod;
return cnt[key];
}
int main()
{
while(scanf("%d", &n) != EOF)
{
int i, j, ans = 0;
memset(hash, 0, sizeof(hash));
memset(cnt, 0, sizeof(cnt));
for(i = 1; i <= n; i ++)
for(j = 0; j < 4; j ++)
scanf("%d", &a[i][j]);
for(i = 1; i <= n; i ++)
for(j = 1; j <= n; j ++)
make_hash(a[i][0] + a[j][1]);
for(i = 1; i <= n; i ++)
for(j = 1; j <= n; j ++)
ans += get_num(-(a[i][2] + a[j][3]));
printf("%d\n", ans);
}
}