Skip to content

11224: 【原1224】hash

题目

题目描述

author: DS TA 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/1224

Description

现在给出A,B,C,D四个集合,每个集合中元素的个数n都是相同的,现在从每个集合中任取出一个数,记为a,b,c,d,现在要求统计有多少组不同的(a,b,c,d)使得a+b+c+d=0。

注意请写散列表类。

Input Format

第一行为各集合中元素的个数n;

第二行到第n+1行,每行有4个数字,依次为A,B,C,D中的一个元素。

Output Format

一行,为不同的(a,b,c,d)使得a+b+c+d=0的组数。

Sample Input

6
-45 22 42 -16
-41 -27 56 30
-36 53 -37 77
-36 30 -75 -46
26 -38 -10 62
-32 -54 -6 45

Sample Output

5

Limits

a,b,c,d的绝对值小于1000000,n小于500

Tips

将式子变形为(a+b)=-(c+d),可以将A,B两集合中元素相加得到n^2个和的集合E,散列存储后,对C,D两集合中元素任意取和,查找和在E中出现的次数,累加即为解。

BugenZhao's solution

//
// Created by BugenZhao on 2019/5/29.
//

//
// Created by BugenZhao on 2019/5/29.
//

#ifndef SBL_BSEPARATECHAININGHASHST_H
#define SBL_BSEPARATECHAININGHASHST_H


template<typename Key, typename Value, typename Hasher>
class BSeparateChainingHashST {
    static constexpr int INIT_CAPACITY = 4;

    class Pair {
    public:
        Key key;
        Value value;
    };

    class Node {
    public:
        Pair pair;
        Node *next;

        Node(const Pair &pair, Node *next = nullptr) : pair(pair), next(next) {}

        Node() : next(nullptr) {}
    };

    int n;
    int m;
    Hasher hasher;
    Node **st;

private:
    int hash(const Key &key) {
return (hasher(key) & 0x7fffffff) % m;
    }

public:
    BSeparateChainingHashST() : BSeparateChainingHashST(INIT_CAPACITY) {}

    BSeparateChainingHashST(int m) : m(m) {
        n = 0;
        st = new Node *[m]{};
    }

    virtual ~BSeparateChainingHashST() {
        for (int i = 0; i < m; ++i) {
            Node *p = st[i];
            Node *q;
            while (p) {
                q = p->next;
                delete p;
                p = q;
            }
        }
        delete[] st;
    }

    int size() {
        return n;
    }

    bool isEmpty() {
        return size() == 0;
    }

    bool contains(const Key &key) {
        return get(key) != nullptr;
    }

    Pair *get(const Key &key) {
        int i = hash(key);
        Node *p = st[i];
        while (p) {
            if (p->pair.key == key) return &(p->pair);
            p = p->next;
        }
        return nullptr;
    }

    void put(const Key &key, const Value &val) {
//        if (n >= 10 * m) resize(2 * m);

        int i = hash(key);
        Node *p = st[i];
        while (p) {
            if (p->pair.key == key) {
                p->pair.value = val;
                return;
            }
            p = p->next;
        }
        ++n;
        st[i] = new Node(Pair{key, val}, st[i]);
    }

    void increment(const Key &key) {
        int i = hash(key);
        Node *p = st[i];
        while (p) {
            if (p->pair.key == key) {
                ++p->pair.value;
                return;
            }
            p = p->next;
        }
        ++n;
        st[i] = new Node(Pair{key, 1}, st[i]);
    }

    void remove(const Key &key) {
        int i = hash(key);
        Node *p = st[i];

        if (st[i] == nullptr) return;

        if (st[i]->pair.key == key) {
            st[i] = st[i]->next;
            delete p;
            --n;
        } else {
            while (p->next) {
                if (p->next->pair.key == key) {
                    auto q = p->next;
                    p->next = q->next;
                    delete q;
                    --n;
                    break;
                }
                p = p->next;
            }
        }
    }

};

#endif //SBL_BSEPARATECHAININGHASHST_H


#include <iostream>
#include <string>

using std::ios, std::cin, std::cout, std::endl, std::string;
using ll = long long;

struct hasher {
    inline int operator()(int i) {
        return i + 2000000;
    }
};

int main() {
    int n;
    scanf("%d", &n);
    auto a = new int[n];
    auto b = new int[n];
    auto c = new int[n];
    auto d = new int[n];
    for (int i = 0; i < n; ++i) {
        scanf("%d%d%d%d", a + i, b + i, c + i, d + i);
    }
    BSeparateChainingHashST<int, int, hasher> st(4000001);
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            st.increment(a[i] + b[j]);
        }
    }

    ll ans = 0;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            auto p = st.get(-c[i] - d[j]);
            if (p) ans += p->value;
        }
    }

    printf("%ld", ans);
    return 0;
}

ligongzzz's solution

#include "iostream"
#include "cstring"
using namespace std;

constexpr int mod = 1000009;

class type {
public:
    int key = -99999999;
    int val = 0;
};

int val_data[509][4] = { 0 };
type hash_map[mod];

int get_pos(int key) {
    int ans = (key + 2000009) % mod;
    for (; hash_map[ans].key != key; ans = (ans + 1) % mod) {
        if (hash_map[ans].key <= -99999999) {
            hash_map[ans].key = key;
            break;
        }
    }
    return ans;
}

int main() {
    int n;
    scanf("%d", &n);

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < 4; ++j)
            scanf("%d", &val_data[i][j]);
    }

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            ++hash_map[get_pos(val_data[i][0] + val_data[j][1])].val;
        }
    }

    int ans = 0;

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            ans += hash_map[get_pos(-val_data[i][2] - val_data[j][3])].val;
        }
    }

    cout << ans;

    return 0;
}

skyzh's solution

#include <iostream>
#include <cstring>

using namespace std;

unsigned alex_hash(long long i) {
    return i;
}

bool equal(long long a, long long b) { return a == b; }

template<typename K, typename V>
struct HashMap {
    struct Pair {
        bool used;
        K key;
        V value;
    } *data;
    static const unsigned cap = 1048576;

    HashMap() {
        data = new Pair[cap];
        memset(data, 0, sizeof(Pair) * cap);
    }

    V &visit(const K key) {
        unsigned pos = alex_hash(key) % cap;
        while (data[pos].used) {
            if (equal(key, data[pos].key)) {
                break;
            }
            ++pos;
            if (pos >= cap) pos = 0;
        }
        if (!data[pos].used) {
            data[pos].used = true;
            data[pos].key = key;
        }
        return data[pos].value;
    }
};

HashMap<long long, int> hash_map;

const int MAX_SET = 500;

long long A[MAX_SET], B[MAX_SET], C[MAX_SET], D[MAX_SET];

int main() {
    int N;
    cin >> N;
    for (int i = 0; i < N; i++) {
        cin >> A[i] >> B[i] >> C[i] >> D[i];
    }
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            ++hash_map.visit(A[i] + B[j]);
        }
    }
    long long ans = 0;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            ans += hash_map.visit(- C[i] - D[j]);
        }
    }
    cout << ans << endl;
    return 0;
}