Hash Function

题目描述

For a given set S={a0,a1,a2,...,an−1}S = \{a_0, a_1, a_2, ..., a_{n-1}\}S={a0​,a1​,a2​,...,an−1​}, we called a hash function fS(x)f_S(x)fS​(x) perfect hash function of S, if it satisfies ∀0≤i<j<n,fS(ai)≠fS(aj)\forall 0 \leq i < j < n, f_S(a_i) \neq f_S(a_j)∀0≤i<j<n,fS​(ai​)​=fS​(aj​).

Given a set S with non-negative integers, please find the minimum positive integer seed that function hseed(x)=xmod  seedh_{seed}(x) = x \mod seedhseed​(x)=xmodseed is a perfect hash function of S.

输入描述:

The first line of input contains one integer $n$, describing the size of set S.The second line contains n(1≤n≤500000)n(1 \leq n \le 500000)n(1≤n≤500000) integers a0,...,an−1a_0,...,a_{n-1}a0​,...,an−1​, describing the elements in S.It is guaranteed that ∀0≤i<j<n,ai≠aj,0≤ai≤500000\forall 0 \leq i < j < n, a_i \ne a_j, 0 \le a_i \le 500000∀0≤i<j<n,ai​​=aj​,0≤ai​≤500000.

输出描述:

Output one integer in a line, indicating the answer.

示例1

输入

复制

3
2 3 4

输出

复制

3

示例2

输入

复制

3
1 2 4

输出

复制

4

示例3

输入

复制

10
0 7 23 18 29 27 6 28 24 11

输出

复制

15

题意:给出的散列集合里面是一些互不相等的数,我们需要找一个最小的正整数x,使集合里的每个数mod x之后仍是互不相等的数。

思路:先将散列集合由小到大排序,排序完最大的数为a[n]。首先考虑mod,因为给的集合的数互不相同,所以无论给的数再小,最大的也应该>=n,所以最小的mod应该在

n -  a[n]+1之间,其次考虑如果集合里的数比mod小,求余后仍为mod,所以一开始就标记所有在集合里的数为true,等会逆着遍历时如果比mod大的数求余后仍和原来集合已经存在的数不相同,就满足条件。

代码如下:

#include <bits/stdc++.h>
using namespace std;
#define N 500010
int n,a[N];
bool vis[N];
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        vis[a[i]]=true;
    }
    sort(a+1,a+n+1);
    for(int i=n;i<=a[n]+1;i++){//最大比集合中最大的数大一,因为如果模出来都等于自身,也是可以的,且满足最小
        int flag=1;
        for(int j=n;a[j]>=i;j--){//比i小的模i模模出来是自身,所以只考虑>=i的
            if(vis[a[j]%i]){
                flag=0;
                break;
            }
        }
        if(flag){
            cout<<i<<endl;//满足条件的最小值,输出,并结束循环
            break;
        }
    }
    return 0;
}

附上一点关于散列的知识:

常见的哈希函数

原理参考《算法导论》

一、除法散列函数

根据描述实现算法,先取对应种子

int hash_mod_seed(int n, int iCheck) {//存放n个关键字,一次不成功的查找要检查iCheck个关键字,默认一个字符是8位int iStart= n / iCheck, prime = (iStart == 1) ? 2 : iStart;assert(iCheck >= 0 && iCheck <= 8);//odd起始要跳过已经判断了的奇数for (int j = 0, odd = (iStart % 2 == 0) ? iStart / 2 : (iStart - 1) / 2 + 1;j < 8 - iCheck; odd++) {//生成一个素数bool fPrime = true;for (int k = 2; k <= sqrt(prime); k++)if (prime % k == 0) {fPrime = false;break;}if (fPrime) //记录素数j++;prime = odd * 2 + 1;//待判断的奇数}return prime - 2;
}

关键算法实现

int hash_mod(int key, int seed) {return key % seed;
}

二、乘法散列函数

根据算法描述实现(应用时,slot大小是2^p,此函数无论如何映射,不会超出slot大小)

int hash_mul(int key, int w, int p) {//w指关键字int是32位,p是映射后截取的最高有效位__int64 s = (sqrt(5) - 1) / 2 * pow(2, w);__int64 r0 = s*key % (__int64)pow(2, w);return r0 / pow(2, w - p);//高p位有效位
}

 三、全域散列

原理是:假设数组有n个元素,通过除法散列算法中的hash_mod_seed函数取得一个素数种子R。利用系统的随机函数并采用取模的方法生成一个长度位R的数组A,在进行全域哈希时,通过关键字key生成一个类似数组A的数组B。最后,散列的主要算法核心是求A[0]*B[0]+....+A[R-1]*B[R-1]的模(被除数是R*R)

全域散列种子生成

int *hash_seed(int *pKey, int R) {//pKey为NULL时表示初始种子,并作为hash_full函数中的v参数传入int *v = new int[R], key;memset(v, 0, R * sizeof(R));if (pKey == NULL) {srand(time(NULL));for (int i = 0; i < R; i++)v[i] = rand() % R;}else {key = *pKey;for (int i = 0; i < R && key; i++) {v[i] = key % R;key = key / R;}}return v;
}

对应的种子释放

void hash_seed_free(int *v) {delete[] v;
}

关键函数,全域散列算法实现(应用时,slot大小是R*R)

int hash_full(int key, int R, int *v) {//R是hash_mod_seed(n, 3),M是hash_mod_seed^2int slot = 0, M = R*R;int *numV = hash_seed(&key, R);for (int i = 0; i < R; i++)slot += numV[i] * v[i];hash_seed_free(numV);return slot % M;
}

为了方便大家测试代码,我还是补一个全域散列的打印函数

void hash_full_print(int *A, int n) {int R = hash_mod_seed(n, 3);int *v = hash_seed(NULL, R), *hash = new int[R*R];memset(hash, 0, sizeof(int)*R*R);printf("hash seed=%d, slot size=%d\n", R, R*R);for (int i = 0; i < n; i++) {int m = hash_full(A[i], R, v);while (hash[m]) //若数据存在,则循环后移一位,注意:当散列全满了,这里是一个死循环,实际应用中,请自行添加判断m = (m + 1) % (R*R);hash[m] = A[i];printf("[%d] is %d\n", m, hash[m]);}hash_seed_free(v);delete[] hash;
}

结果补一张(很明显至少有一个碰撞,但是通过后移一位,解决了这个问题,总体来说效果很不错。最后完全散列很容易在此基础上修改,就不发代码了。各位创新下!!!思路就是在每个对应hash值处,生成一个R*R链表,看需求实现吧!!!):

第二次运行就不存在碰撞了,上一个测试图吧。

所有代码均经过测试,结果正确

H Hash Function相关推荐

  1. 2021牛客暑期多校训练营1 H Hash Function FFT\NTT

    传送门 文章目录 题意: 思路: 题意: 给你一个数组aaa,你需要找一个最小的模数xxx,使得aaa中每个数都模上xxx之后互不相同. n≤5e5,ai≤5e5,ai!=ajn\le5e5,a_i\ ...

  2. FFT ---- 2021牛客多校第一场 H Hash Function

    题目链接 题目大意: 解题思路: 首先我们知道任意两个数%seed\%seed%seed都不相同→\rightarrow→(aj−ai)%seed≠0(∀ai≤aj)(a_j-a_i)\%seed\n ...

  3. 2021牛客第一场H.Hash Function—FFT求差值的卷

    https://ac.nowcoder.com/acm/contest/11166/H 官方题解. 比赛时,我们都是用暴力写的,数据太弱了,今天突然想起来,用fft写了一下. 主要使用fft求差值的卷 ...

  4. 2021牛客多校1 - Hash Function(思维+FFT)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的序列,现在要求找到一个 seedseedseed,使得所有数字变为 a[i]=a[i]modseeda[i]=a[i]\mod seeda[i] ...

  5. Hash Function

    Hash Function 文章目录 题意: 题解: 代码 NTT代码 FFT代码 题意: 给定n个互不相同的数,找一个最小的模域,使得它们在这个模域下互不相同.n<=5e5 题解: 考虑两个数 ...

  6. hash function/ hash table 背后的数学基础

    原文请见:Load Balancing and the Power of Hashing 如果你参加一次软件工程师的面试并你被问到一个很难的有关算法的题目,那么你最好考虑使用散列函数(hash tab ...

  7. Hash Function 2021牛客暑期多校训练营1 数论 + NTT

    Hash Function solution 任意选择该集合中的两个数,a,b,由于a%mod<>b%mod任意选择该集合中的两个数,a,b,由于a\%mod<>b\%mod任 ...

  8. POSEIDON: A New Hash Function for Zero-Knowledge Proof Systems 学习笔记

    1. 引言 Grassi等人2019年论文<POSEIDON: A New Hash Function for Zero-Knowledge Proof Systems>. 前序博客有: ...

  9. 1.1. Cryptographic Hash Function.加密哈希函数

    <BITCOIN AND CRYPTOCURRENCY TECHNOLOGIES>Chapter 1系列 1.1. Cryptographic Hash Function.加密哈希函数 目 ...

最新文章

  1. Python成长之路第一篇(4)_if,for,while条件语句
  2. 定义指令时“控制器”,“链接”和“编译”函数之间的区别
  3. 磁盘镜像分析工具TSK
  4. 利用树求解算术表达式的值
  5. 干货 | 深入仓储管理系统你需要了解的15件事
  6. Windows平台下 找回已丢失的MySql root 用户密码
  7. C#EF中,使用类似于SQL中的% 模糊查询
  8. C语言期末成绩计算机平均分,用C语言编程平均分数
  9. java中file对象_Java中File对象的常用方法
  10. programming review (c++): (1)vector, linked list, stack, queue, map, string, bit manipulation
  11. CALayer与UIView区别和联系【转】
  12. 读书札记:Fiddler--中文版(本人自己汉化的)下载
  13. 中兴盒子ZTE-B860AV1.1T、AV2.1-通刷-线刷固件
  14. 计算机字体管理软件,字体管理软件有哪些?字体管理软件推荐
  15. 基于OPENCV的图像识别(JAVA版本)
  16. 系统保留分区删除_什么是系统保留分区,您可以删除它吗?
  17. 转帖 -- 仙4语录
  18. EA开发系列---技术指标的使用
  19. AcWing 838.堆排序
  20. PageRank背后的数学

热门文章

  1. WhatsApp网页版登陆,WhatsApp官网入口
  2. 天宝营养冲刺深交所:年营收12.5亿 拟募资7亿
  3. Walmart API 授权流程解析
  4. Nginx遇到无法创建或打开nginx.pid的解决方法
  5. LeaRun.net快速开发动态表单
  6. Centos7 glibc库升级到2.23(实测可行)
  7. D0g3 CTF-WEB
  8. leetcode *210. 课程表 II(拓补排序)(2020.5.17)
  9. 携职教育:四川2022年人力资源管理师考试报名通知
  10. setenv设置环境变量_setenv命令教程在Linux中添加,删除和更改环境变量