跳转至

哈希碰撞

假设我们的哈希函数实现的足够好,每个元素的哈希值都是独立均匀随机的在值域 \(d\) 内撒一个点,那么 \(n\) 个元素哈希后碰撞的概率可以写为:

\[ 1-\frac{\binom{d}{n}}{d^n} \]

其在 \(d=10^9,\ n=10^6\) 时非常接近于 \(1\),因此不建议使用模数 \(10^9\) 级别的单模哈希。

其在 \(d=10^{18},\ n=10^6\) 时非常接近于 \(0\),因此可以使用模数 \(10^{18}\) 级别(\(2^{61}-1\))的单模哈希。

这里提供一个计算随机撒点碰撞概率的程序。

#include<iostream>
#include<random>
#define int long long
#define ld long double
using namespace std;

// 就是下降幂除以普通幂
ld calc1(int n, int d) {
    ld res = 1;
    int j = 0;
    for(int i = d - n + 1; i <= d; i++) {
        res = res * i;
        while(j < n && res >= 1) { res /= d; ++j; }
    }
    while(j < n) { res /= d; ++j; }
    return res;
}

// example
// 在值域 1e18 内撒 1e6 个点
int n = 1e6;
int d = 1e18;

signed main() {

    // cin >> n >> d;
    // 不碰撞的概率
    cout << (1.0l - calc1(n, d)) << endl;

    return 0;
}