今天,带大家看一看一道思维题。。。

Hash 键值 (hash)

题目描述

Marser沉迷hash无法自拔,然而他发现自己记不住hash键值了……

Marser使用的hash函数是一个单纯的取模运算,每一个数i被对应到i mod p。他现在有一个数列,他采用这种方法,把每一个数对应到一个键值i mod p。他想知道对于给定的模数p和键值r,所有对应到该键值的数的和为多少。同时,Marser可能会发现他的数列出了一些问题,所以他还想随时更改数列中任意一项的值。

现在Marser有q个请求,每个请求可能是修改或是询问。对于每一个询问,你需要给出正确的答案。如果你不能在1s内正确回答所有询问,Marser就会让hotwords把你给续了。

输入格式

从文件hash.in读入。

第一行两个整数n,q,表示数列长度和请求数量。

第二行n个整数,表示初始的序列。

接下来m行,每行三个整数opt,x,y;

若opt=1,则询问在mod x时,所有对应到键值y的数的和。

若opt=2,则将数列第x项修改为y。

输出格式

输出到文件hash.out中。

样例

样例输入 1

10 5
1 2 3 4 5 6 7 8 9 10
1 2 1
2 1 20
1 3 1
2 5 1
1 5 0

样例输出 1

25
41
11

首先,我们发现这是一道水题

轻轻松松写下下面的代码

#include <bits/stdc++.h>
using namespace std;
int a[100005]; int main() {
int n, m;
freopen("hash.in","r",stdin);
freopen("hash.out","w",stdout);//文件输入输出
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
for (int i = 1; i <= m; ++i) {
int x;
scanf("%d", &x);
if (x == 1) {
int x1, x2, ans = 0;
scanf("%d%d", &x1, &x2);
for (int i = x2; i <= n; i += x1) { //不需要一个一个枚举,只需要算x1的倍数就行了;
ans += a[i];
}
printf("%d\n", ans);
}
if (x == 2) {
int x1, x2;
scanf("%d%d", &x1, &x2);
a[x1] = x2; //维护
}
}
}

然后我们发现:

轻轻松松超时

竟然可以拿30分!!!

咳咳,言归正传,我们开始讨论100分的代码

(开始吟唱)

Frist:

我们需要算一下时间复杂度

原代码时间复杂度为O(n+mn/x1);

所以我们的代码一定要小于这个时间复杂度;

second

我们发现,无论如何原代码的时间复杂度是减少不了的了至少我没想出啦。。。,所以只能:

另辟蹊径:

仔细一想,不难得出:如果我们能在x1,x2读入的时候,就直接输出ans,那么时间复杂度肯定会大大降低;

那么我们怎么才可以实现这种操作呢?

首先,定义一个名为sum的二维数组,sum[i][j]表示所有模i余j的数的总和;

再输入一个a[i]以后,就用一重循环遍历,代码如下:

for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
for(int j=1;j<n;++j){
sum[j][i%j]+=a[i]; //除j模(i%j);
}
}

这样,我们其实就可以达成输入就输出啦!!!

但我们再来算算时间复杂度O=(nn+mn)(为什么是mn呢?因为当我们更改一个值时,那么sum数组的之也要改);

然后我们神奇的发现,时间复杂度竟然比原来还大!

那么,如果我们不遍历所有值,而是只遍历log(n),再把x1>log(n)的情况用第一种方法运算呢???

再算算时间复杂度:O=(n*log(m)+MAX(mn/x1,mn));

化简一下:O=(n*log(m)+mn/x1);

然后我们就可以过剩下的测试点啦!!!
上代码!!!:

再次声明:如果你要抄代码,只会害了你自己。。。

#include<bits/stdc++.h>
using namespace std;
int a[1000005],sum[1005][1005]; //sum[i][j]等于所有除以i余j的数的和; int main(){
freopen("hash.in","r",stdin);
freopen("hash.out","w",stdout); //文件输入输出
int n,m;
scanf("%d%d",&n,&m);
int num=sqrt(n);
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
for(int j=1;j<num;j++){
sum[j][i%j]+=a[i]; //对sum进行赋值,循环j模拟i除以的数之和;
}
}
for(int i=1;i<=m;++i){
int x;
scanf("%d",&x);
if(x==1){
int x1,x2,ans=0;
scanf("%d%d",&x1,&x2);
if(x1<num){//如果x1<num,说明x1在sum处理的范围内;
printf("%d\n",sum[x1][x2]); //直接通过前文对sum的处理输出;
}
else{
for(int i=x2;i<=n;i+=x1){ //方法一;
ans+=a[i];
}
printf("%d\n",ans);
}
}
if(x==2){
int x1,x2;
scanf("%d%d",&x1,&x2);
for(int i=1;i<=num;i++)
sum[i][x1%i]=sum[i][x1%i]-a[x1]+x2; //维护sum数组,把a[x1]覆盖成x2,并确保sum里的值正确;
a[x1]=x2; //对a[i]也要进行维护;
}
}
}

2018-10-14普及模拟赛」Hash 键值 (hash)的更多相关文章

  1. 2018.10.16 NOIP模拟赛解题报告

    心路历程 预计得分:\(100 + 100 + 20 = 220\) 实际得分:\(100 + 100 + 30 = 230\) 辣鸡模拟赛.. T1T2都是一眼题,T3考验卡常数还只有一档暴力分. ...

  2. 2018.10.29 NOIP2018模拟赛 解题报告

    得分: \(70+60+0=130\)(\(T3\)来不及打了,结果爆\(0\)) \(T1\):简单的求和(点此看题面) 原题: [HDU4473]Exam 这道题其实就是上面那题的弱化版,只不过把 ...

  3. 2018.10.03 NOIP+ 模拟赛 解题报告

    得分: \(30+5+0=35\)(考得真不咋滴) \(T1\):奥义商店(点此看题面) 以为很简单,对着这题想了一个多小时,最后果断打了个暴力交了... ... 看完题解发现其实也不是很难. 对于\ ...

  4. 2018.10.26 NOIP2018模拟赛 解题报告

    得分: \(0+10+10=20\)(\(T1\)死于假题面,\(T3\)死于细节... ...) \(P.S.\)由于原题是图片,所以我没有上传题目描述,只有数据. \(T1\):颜料大乱斗(点此看 ...

  5. 2018.10.24 NOIP2018模拟赛 解题报告

    得分: \(100+0+100=200\)(\(T2\)悲惨爆\(0\)) \(P.S.\)由于原题是图片,所以我没有上传题目描述,只有数据. \(T1\):query(点此看题面) 熟悉主席树的人都 ...

  6. 2018.10.30 NOIp模拟赛 T1 改造二叉树

    [题目描述] 小Y在学树论时看到了有关二叉树的介绍:在计算机科学中,二叉树是每个结点最多有两个子结点的有序树.通常子结点被称作“左孩子”和“右孩子”.二叉树被用作二叉搜索树和二叉堆.随后他又和他人讨论 ...

  7. 2018.10.17校内模拟赛:T2神光

    题面:pdf 首先排序,二分,然后怎么判定是否可行. 最简单的思路是,dp[i][j][k],到第i个,用了j次红光,k次绿光,前i个点都选上了,是否可行.然后转移就行. 然后考试的时候就想到这了,往 ...

  8. 2018.10.30 NOIp模拟赛T2 数字对

    [题目描述] 小 H 是个善于思考的学生,现在她又在思考一个有关序列的问题.        她的面前浮现出一个长度为 n 的序列{ai},她想找出一段区间[L, R](1 <= L <= ...

  9. 10.17 NOIP模拟赛

    目录 2018.10.17 NOIP模拟赛 A 咒语curse B 神光light(二分 DP) C 迷宫maze(次短路) 考试代码 B 2018.10.17 NOIP模拟赛 时间:1h15min( ...

随机推荐

  1. Select Screen 0 with xrandr Ask QuestionScreen 0" here describes your whole virtual display made of these two outputs: eDP-1-

    Screen 0" here describes your whole virtual display made of these two outputs: eDP-1-1: physica ...

  2. CPU缓存是位于CPU与内存之间的临时数据交换器,它的容量比内存小的多但是交换速度却比内存要快得多。CPU缓存一般直接跟CPU芯片集成或位于主板总线互连的独立芯片上

    一.什么是CPU缓存 1. CPU缓存的来历 众所周知,CPU是计算机的大脑,它负责执行程序的指令,而内存负责存数据, 包括程序自身的数据.在很多年前,CPU的频率与内存总线的频率在同一层面上.内存的 ...

  3. OpenStack常见面试题

    现在,大多数公司都试图将它们的 IT 基础设施和电信设施迁移到私有云, 如 OpenStack.如果你打算面试 OpenStack 管理员这个岗位,那么下面列出的这些面试问题可能会帮助你通过面试. Q ...

  4. Spring AOP 框架

    引言 要掌握 Spring AOP 框架,需要弄明白 AOP 的概念. AOP 概念 AOP(Aspect Oriented Programming的缩写,翻译为面向方面或面向切面编程),通过预编译方 ...

  5. 重新整理 .net core 实践篇————依赖注入应用之生命法则[三]

    前言 该章演示依赖注入中,对象的释放行为. 紧接上文表示,演示: services.AddSingleton<IMySingletonService, MySingletonService> ...

  6. 【Web前端HTML5&CSS3】12-字体

    笔记来源:尚硅谷Web前端HTML5&CSS3初学者零基础入门全套完整版 目录 字体 1. 字体相关的样式 2. font-family 3. 几种字体 手写体 艺术体 乱码字体 中文字体 4 ...

  7. idea开发web项目框架失效和无法启动问题

    不会配置idea的javaweb环境的小伙伴可以点击此链接 idea最新版,配置javaweb环境 很多小伙伴用idea开发web项目可能会出现所有代码都写对了但是无论如何都没法运行的情况,eclip ...

  8. 使用shell脚本循环处理文本

    公司是使用puppet来进行配置管理, 某天修改完puppet后领导回复: 我们有一个文档cabinet.txt记录了物理机器所在的机柜, 除了文档里的其他机器都是虚拟机或云服务器, 对虚拟机的pup ...

  9. TVM交叉编译和远程RPC

    TVM交叉编译和远程RPC 本文介绍了TVM中使用RPC的交叉编译和远程设备执行. 使用交叉编译和RPC,可以在本地计算机上编译程序,然后在远程设备上运行它.当远程设备资源受到限制时(如Raspber ...

  10. TensorFlow文本情感分析实现

    TensorFlow文本情感分析实现 前面介绍了如何将卷积网络应用于图像.本文将把相似的想法应用于文本. 文本和图像有什么共同之处?乍一看很少.但是,如果将句子或文档表示为矩阵,则该矩阵与其中每个单元 ...