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

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. openstack创建vlan网络并配置网络设备

    1.在管理员-->网络-->创建网络. 2.填写网络信息,这里要划分新的VLAN,注意在物理网络中填写的事VLAN,段ID指的是vlan的id 3.创建的网络. 4.创建子网,在里面修改子 ...

  2. windows怎么访问linux的samba共享目录

    windows怎么访问linux的samba共享目录 听语音 原创 | 浏览:6976 | 更新:2018-07-31 13:20 | 标签:LINUX WINDOWS 1 2 3 4 5 6 7 分 ...

  3. Scala 关键字

    Java关键字 Java 一共有 50 个关键字(keywords),其中有 2 个是保留字,目前还不曾用到:goto 和 const.true.false 和 null 看起来很像关键字,但实际上只 ...

  4. Java 中布尔(boolean)类型占用多少个字节

    为什么要问这个问题,首先在Java中定义的八种基本数据类型中,除了其它七种类型都有明确的内存占用字节数外,就 boolean 类型没有给出具体的占用字节数,因为对虚拟机来说根本就不存在 boolean ...

  5. 十二、.net core(.NET 6)添加通用的访问webapi的方法(包括HttpClient和HttpWebRequest)

    开发通用的访问webapi方法. 在common工具文件夹下,新建一个类库项目:Wsk.Core.WebHelper,并引用Package包项目,然后新建一个类HttpClientHelper,用于使 ...

  6. JMeter逻辑控制器完整介绍

    JMeter逻辑控制器可以对元件的执行逻辑进行控制,就像编程一样,实现业务需求. JMeter包括了以下逻辑控制器: 一共17种.除了仅一次控制器外,其他控制器下可以嵌套别的种类的逻辑控制器. If ...

  7. 微信内 H5 页面自定义分享

    起源: 最近公司在做一个活动的h5页面,在微信内打开时需要进行微信授权,然后后端会重定向到这个页面并且携带了一些参数(openid等).问题是点击微信的原生分享时,会把携带的这些参数一起分享出去,等于 ...

  8. SLAM架构的两篇顶会论文解析

    SLAM架构的两篇顶会论文解析 一. 基于superpoint的词袋和图验证的鲁棒闭环检测 标题:Robust Loop Closure Detection Based on Bag of Super ...

  9. 深度学习框架集成平台C++ Guide指南

    深度学习框架集成平台C++ Guide指南 这个指南详细地介绍了神经网络C++的API,并介绍了许多不同的方法来处理模型. 提示 所有框架运行时接口都是相同的,因此本指南适用于所有受支持框架(包括Te ...

  10. CUDA刷新:GPU计算生态系统

    CUDA刷新:GPU计算生态系统 CUDA Refresher: The GPU Computing Ecosystem 这是CUDA Refresher系列的第三篇文章,其目标是刷新CUDA中的关键 ...