PTA甲级—常用技巧与算法
散列
1078 Hashing (25 分)
Quadratic probing (with positive increments only) is used to solve the collisions.
这句话说的是使用平方探测法来解决哈希冲突,Linear Probing(线性探测法)、Quadratic probing(平方探测法)这种专业术语在平常的学习中应当认真记忆而不是认为不重要,因为这句话一开始看不懂,想当然认不重要就略过了,那结果多半WA。
知道了解决办法之后,需要处理的一个问题就是我们如何知道插入失败?
假设$x<y$,由$h(k) + x^2 = h(k) + y^2 \quad (mod \ p)$得:
$$ x^2 = y^2 \quad(mod \ p)$$
$$ (x-y)(x+y) = 0 \quad(mod \ p)$$
由上述式子推导可发现$p$是一个循环节,如果从$0 \sim p-1$进行枚举仍然找不到位置的话即可认为插入失败
这道题要求的是$with \ positive \ increments \ only$,去掉这个限制条件后,以增量序列$1^2, -1^2, 2^2, -2^2 \dots, x^2, -x^2$且$x<=p/2$循环试探下一个存储地址即可,证明同上可得(tips:大与2/p的部分可以由p减去小于2/p的部分得到)
还需要注意的一个点:1不是素数,需要在isPrime函数中加以判断

#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#define ll long long
#define inf 0x3f3f3f3f
#define pb push_back
#define pii pair<int,int>
using namespace std;
const int maxn = 1e6+100;
int p, n, tmp;
bool vis[maxn];
bool isPrime(int x){
if(x==1) return false;
for(int i = 2; i*i <= x; i++)
if(x%i==0) return false;
return true;
}
int main(){
scanf("%d%d", &p, &n);
while(!isPrime(p)) p++;
while(n--){
scanf("%d", &tmp);
int x = tmp%p, y = x, inc = -1;
while(inc<p&&vis[y]) inc++, y = (x+inc*inc)%p;
if(inc!=p) printf("%d", y), vis[y] = 1;
else printf("-");
if(n) printf(" ");
}
}
补充资料:
线性探测是按线性方法一个一个找,只要表里有空位总能将元素填入;而二次探测有可能出现表中有空间但平方探测找不到的情况
线性探测容易聚集,二次探测聚集情况较线性探测要好。
二次探测有时候探测不到整个散列表空间,是其一大缺陷。但是经过数学家的研究,散列表长度TableSize是某个4k+3(k是正整数)形式的素数时,平方探测法就可以探查到整个散列表空间.
Reference:
https://www.icourse163.org/learn/ZJU-93001?tid=1003997005#/learn/content?type=detail&id=1007588520
https://www.nowcoder.com/discuss/67780
https://en.wikipedia.org/wiki/Quadratic_probing
https://blog.csdn.net/qq_37142034/article/details/87903983
https://blog.csdn.net/pennyliang/article/details/5446961
1145 Hashing - Average Search Time (25 分)
这道题相当于1078的扩展,关键在于如何求不在散列表中的元素的平均查找次数。边界值显然为p+1,当查找到已经查找过的单元格后就知道查找失败了;在这个过程中如果发现有空位也能说明该元素不在单元格中

#include <cstdio>
using namespace std;
const int maxn = 1e6+100;
int p, n, m, tmp, h[maxn];
bool vis[maxn];
bool isPrime(int x){
if(x==1) return false;
for(int i = 2; i*i <= x; i++)
if(x%i==0) return false;
return true;
}
int main(){
scanf("%d%d%d", &p, &n, &m);
while(!isPrime(p)) p++;
while(n--){
scanf("%d", &tmp);
int x = tmp%p, y = x, inc = 0;
while(vis[y]&&++inc<p) y = (x+inc*inc)%p;
if(inc!=p) h[y] = tmp, vis[y] = 1;
else printf("%d cannot be inserted.\n", tmp);
}
int cnt = m, sum = 0;
while(m--){
scanf("%d", &tmp);
int x = tmp%p, y = x, inc = 0;
while(h[y]!=tmp&&vis[y]&&++inc<p) y = (x+inc*inc)%p;
sum += inc+1;
}
printf("%.1f", 1.0*sum/cnt);
}
PTA甲级—常用技巧与算法的更多相关文章
- python算法常用技巧与内置库
python算法常用技巧与内置库 近些年随着python的越来越火,python也渐渐成为了很多程序员的喜爱.许多程序员已经开始使用python作为第一语言来刷题. 最近我在用python刷题的时候想 ...
- JavaScript实现常用的排序算法
▓▓▓▓▓▓ 大致介绍 由于最近要考试复习,所以学习js的时间少了 -_-||,考试完还会继续的努力学习,这次用原生的JavaScript实现以前学习的常用的排序算法,有冒泡排序.快速排序.直接插入排 ...
- 【shell 大系】Linux Shell常用技巧
在最近的日常工作中由于经常会和Linux服务器打交道,如Oracle性能优化.我们数据采集服务器的资源利用率监控,以及Debug服务器代码并解决其效率和稳定性等问题.因此这段时间总结的有关Linux ...
- oracle存储过程常用技巧
我们在进行pl/sql编程时打交道最多的就是存储过程了.存储过程的结构是非常的简单的,我们在这里除了学习存储过程的基本结构外,还会学习编写存储过程时相关的一些实用的知识.如:游标的处理,异常的处理,集 ...
- Vim 常用技巧:
Vim 常用技巧: 将回车由默认的8个空格改为4个空格: 命令:set sw=4 修改tab为4空格: 命令:set ts=4 设置每一级的缩进长度: 命令:set shiftwidth=4 设置文件 ...
- JS~~~ 前端开发一些常用技巧 模块化结构 &&&&& 命名空间处理 奇技淫巧!!!!!!
前端开发一些常用技巧 模块化结构 &&&&& 命名空间处理 奇技淫巧!!!!!!2016-09-29 17 ...
- 常用Java排序算法
常用Java排序算法 冒泡排序 .选择排序.快速排序 package com.javaee.corejava; public class DataSort { public DataSort() { ...
- Android ListView 常用技巧
Android ListView 常用技巧 Android TextView 常用技巧 1.使用ViewHolder提高效率 ViewHolder模式充分利用了ListView的视图缓存机制,避免了每 ...
- JavaScript常用技巧总结(持续添加中...)
在我学习过程中收集的一些常用技巧: typeof x !== undifined 判断x是否已定义: x === Object(x) 判断x是否为对象: Object.keys(x).length ...
随机推荐
- HDU - 3281 dp
题意: 给你b个球,m个楼层,你需要找到一个楼层数k,使得从小于k这个楼层上面扔下去球,而球不会碎.求在最糟糕的情况下你最多要尝试多少次 题解: dp[i][j]表示你有b个球,楼层总数为m,你找到那 ...
- python try异常处理
什么是异常 python异常捕获,在刚开始学的时候,经常会遇到两种报错信息:语法错误和执行的异常. 语法错误在执行的时候就会报错,同时控制端会告诉你错误所在的行: 但即便python程序语法是正确的, ...
- 牛客网多校第4场 J Hash Function 【思维+并查集建边】
题目链接:戳这里 学习博客:戳这里 题意: 有n个空位,给一个数x,如果x%n位数空的,就把x放上去,如果不是空的,就看(x+1)%n是不是空的. 现在给一个已经放过数的状态,求放数字的顺序.(要求字 ...
- 如何用 js 实现一个 new 函数
如何用 js 实现一个 new 函数 原理 new 关键字实现经过了如下过程 创建一个空对象 obj = {} 链接到原型 obj.proto = constructor.prototype 绑定 t ...
- Docker In Action
Docker In Action Docker 实战 https://docs.docker.com/get-started/overview/ Docker Engine Docker Archit ...
- 线上 S1 故障是什么, 线上 S1 故障, 运维故障分级, 运维, 故障分级, P1 级别故障, 故障, P1 , S1
线上 S1 故障是什么 线上 S1 故障, 运维故障分级, 运维, 故障分级, P1 级别故障, 故障, P1 , S1 故障复盘 https://time.geekbang.org/column/a ...
- NGK的去中心化自治实践,更人性化的DAO
2020年,DeFi市场市场火爆的同时,引爆了流动性挖矿的市场.行业内对DAO的思考也在源源不断进行,特别项目治理通证发行之前,DAO的去中心化的治理理念,是区块链属性中的重要的一环,也已引发了不同项 ...
- Mysql之用户认证授权管理
概述 Mysql的认证采用账号密码方式,其中账号由两个部分组成:Host和User:Host为允许登录的客户端Ip,User为当前登录的用户名. 授权没有采用典型的RBAC(基于角色的访问控制),而是 ...
- java: 类 RegisterController 是公共的, 应在名为 RegisterController.java 的文
public声明的类名需要和文件名一致,检查一下
- c#(winform)获取本地打印机
引用 using System.Drawing.Printing; //代码 PrintDocument prtdoc = new PrintDocument(); string strDefault ...