這兩天看文章,看得手又癢了。於是提前開了自己掛的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);
}
}