2018-10-14普及模拟赛」Hash 键值 (hash)
今天,带大家看一看一道思维题。。。
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)的更多相关文章
- 2018.10.16 NOIP模拟赛解题报告
心路历程 预计得分:\(100 + 100 + 20 = 220\) 实际得分:\(100 + 100 + 30 = 230\) 辣鸡模拟赛.. T1T2都是一眼题,T3考验卡常数还只有一档暴力分. ...
- 2018.10.29 NOIP2018模拟赛 解题报告
得分: \(70+60+0=130\)(\(T3\)来不及打了,结果爆\(0\)) \(T1\):简单的求和(点此看题面) 原题: [HDU4473]Exam 这道题其实就是上面那题的弱化版,只不过把 ...
- 2018.10.03 NOIP+ 模拟赛 解题报告
得分: \(30+5+0=35\)(考得真不咋滴) \(T1\):奥义商店(点此看题面) 以为很简单,对着这题想了一个多小时,最后果断打了个暴力交了... ... 看完题解发现其实也不是很难. 对于\ ...
- 2018.10.26 NOIP2018模拟赛 解题报告
得分: \(0+10+10=20\)(\(T1\)死于假题面,\(T3\)死于细节... ...) \(P.S.\)由于原题是图片,所以我没有上传题目描述,只有数据. \(T1\):颜料大乱斗(点此看 ...
- 2018.10.24 NOIP2018模拟赛 解题报告
得分: \(100+0+100=200\)(\(T2\)悲惨爆\(0\)) \(P.S.\)由于原题是图片,所以我没有上传题目描述,只有数据. \(T1\):query(点此看题面) 熟悉主席树的人都 ...
- 2018.10.30 NOIp模拟赛 T1 改造二叉树
[题目描述] 小Y在学树论时看到了有关二叉树的介绍:在计算机科学中,二叉树是每个结点最多有两个子结点的有序树.通常子结点被称作“左孩子”和“右孩子”.二叉树被用作二叉搜索树和二叉堆.随后他又和他人讨论 ...
- 2018.10.17校内模拟赛:T2神光
题面:pdf 首先排序,二分,然后怎么判定是否可行. 最简单的思路是,dp[i][j][k],到第i个,用了j次红光,k次绿光,前i个点都选上了,是否可行.然后转移就行. 然后考试的时候就想到这了,往 ...
- 2018.10.30 NOIp模拟赛T2 数字对
[题目描述] 小 H 是个善于思考的学生,现在她又在思考一个有关序列的问题. 她的面前浮现出一个长度为 n 的序列{ai},她想找出一段区间[L, R](1 <= L <= ...
- 10.17 NOIP模拟赛
目录 2018.10.17 NOIP模拟赛 A 咒语curse B 神光light(二分 DP) C 迷宫maze(次短路) 考试代码 B 2018.10.17 NOIP模拟赛 时间:1h15min( ...
随机推荐
- MySQL配置HeartBeat实现心跳监控和浮动IP
1. 初始化环境配置 /sbin/chkconfig --add mysqld /sbin/chkconfig mysqld on ln -s /usr/local/mysql/bin/mysql / ...
- ltp
1.查找文件 find / -name 'filename' 1 2.查找目录 find / -name 'path' -type d 1 3.查找内容 # find .| xargs grep ...
- Linux自动执行任务
Linux自动执行任务 耗奇害死猫关注 2018.01.04 10:19:45字数 74阅读 142 单次执行用at和batch,周期性任务执行用crontab.任务执行结束后会将结果返回给发起人,通 ...
- Pulsar 下一代消息平台
引言 提起成熟的消息队列或消息引擎,毋庸置疑,大多数人的第一反应一定是 Kafka. Kafka 能够彻底满足海量数据场景下高吞吐.高并发需求,在短短几年内,已经被阿里.腾讯.百度.字节跳动.Netf ...
- MyBatis 高级查询之一对一查询(九)
高级查询之一对一查询 查询条件:根据游戏角色ID,查询账号信息 我们在之前创建的映射器接口 GameMapper.java 中添加接口方法,如下: /** * 根据角色ID查询账号信息 * @para ...
- rm删除破折号开头的文件或目录
转载地址:http://blog.chinaunix.net/uid-25266990-id-3458755.html rm删除(清除)一个或多个文件 -f 选项将强制删除文件,即使这个文件是只读的. ...
- C# DeepClone 深拷贝
常规利用反射进行克隆 public static T CloneModel<T>(T oModel) { var oRes = default(T); var oType = typeof ...
- Django(41)详解异步任务框架Celery
celery介绍 Celery是由Python开发.简单.灵活.可靠的分布式任务队列,是一个处理异步任务的框架,其本质是生产者消费者模型,生产者发送任务到消息队列,消费者负责处理任务.Celery ...
- Runtime PM 处理不当导致的 external abort on non-linefetch 案例分享
硬件平台:某ARM SoC 软件平台:Linux 1 Runtime PM 简介 在介绍 Runtime PM 之前,不妨先看看传统的电源管理.传统的电源管理机制,称之为 System PM(Syst ...
- 通过git将项目传到github上
lenovo@LAPTOP-3KMEN0B2 MINGW64 /e/Users/lenovo/springboot-project/forum $ ls forum.iml HELP.md mvnw* ...