计蒜客 成绩统计 (Hash表)


**链接 : ** Here!

**思路 : ** 如果用 $STL$ 的 $map$ 或者是使用 $unorderedunderline{}map$ 的话是会 $T$ 的, 所以得手写一个 $hash表$. 其实这个题题意一开始看的话还是蛮难以理解的. 但是如果理解了题意, 这道题就非常简单了.

题目样例解析 : 小 $K$ 一共采访了 $5$ 个同学, 他们反馈的结果是 $1, 1, 2, 2, 3$ . 那么, 最优解为 $9$, 下面给出一个表, 表示最优解的详细情况. 首先先给 $5$ 名同学编号 $1, 2, 3, 4, 5$ , $1$ 号同学和 $2$ 号同学都说有 $1$ 个人跟他们成绩一样, 因此可以把 $1,2$ 放到一个集合中, 发现满足要求, 不需要添加新同学($+0$). $3$ 号同学和 $4$ 号同学都说有 $2$ 个人跟他们成绩一样, 因此可以把 $3, 4$ 放到一个集合中, 发现不满足要求, 需要添加新同学($+1$). $5$ 号同学说有 $3$ 个人跟他成绩一样, 因此可以把 $5$ 放到一个集合中, 发现不满足要求, 需要添加新同学($+3$). 因此答案就是 $5 + 0 + 1 + 3 = 9$

**思路 : ** 注意数据范围!注意数据范围!!!


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long ll;
const int MAX_N = 10000019;

ll _hash[MAX_N + 10] = {0}, _count[MAX_N + 10]; 
ll N, M;
ll _seed;

void insert_hash(ll x) {
    ll pos = (x % MAX_N);
    // 处理hash冲突, 如果模一个素数的话...应该很少遇到冲突
    while (_hash[pos] != x && _hash[pos] != 0) {
        pos = pos + 1;
        pos %= MAX_N;
    }
    if (_hash[pos] == 0) {
        _hash[pos] = x;
    }
    ++_count[pos];
}

int main() {
    scanf("%lld%lld", &N, &M);
    for (int i = 0 ; i * 100 < N ; ++i) {
        scanf("%lld", &_seed);
        for (int j = 0 ; j < 100 ; ++j) {
            insert_hash(_seed + 1);
            _seed = (_seed * 109 + 107) % M;
        }
    }
    ll ans = 0;
    for (int i = 0 ; i < MAX_N ; ++i) {
        if (_hash[i] == 0) continue;
        ans += ((_count[i] % (_hash[i]) == 0) ? _count[i] : (ll)(_count[i] / (_hash[i]) + 1) * (ll)(_hash[i]));
    }
    printf("%lld
", ans);
    return 0;
}
原文地址:https://www.cnblogs.com/WArobot/p/7911255.html