2022年CSP初赛模拟考试·第十八套 错题总结与延伸(内部存储器、高精度加法、表达式转换)

总的来说,这套是十分简单的,错了是十分不应该的……


目录

一.内部存储器

题面

相关知识

答案解释 

二.中缀表达式转前缀表达式

题面

知识讲解 

答案解释

三.命题联接词

四.高精度算法(加法)

题面

知识讲解

①逆序存储

②模拟加法运算

③反向输出:

完整代码:

 答案讲解

最后


一.内部存储器

题面

8.计算机启动时,可以通过存储在( )中的引导程序引导操作系统。
(题目来源CCF)

  • A  ROM

  • B RAM

  • C Cache

  • D CPU

相关知识

 在计算机中,内部存储器是可以直接访问的,也名为内存。

  1. 随机访问存储器、(RAM):既可从中读取文件,又可以写入文件。RAM 是一种易失性存储器,意味着当计算机断电时,其中的数据会被清除

  2. 缓存存储器(cache):缓存存储器位于处理器芯片内部,用于临时存储常用的数据和指令。它的目的是提高计算机的访问速度,通过减少对主存储器的访问次数来实现。

  3. 只读存储器(ROM):只读存储器用于存储固定的数据和指令,例如基本的启动程序和系统固件。与RAM不同,ROM是一种非易失性存储器,即使计算机断电也能保持其中的数据内容不变。

答案解释 

从上面加粗标重点的地方可以看出,此题应选A。


二.中缀表达式转前缀表达式

题面

表达式a+b*c-(d+e)的前缀形式是( )
(题目来源CCF)

  • A  abc*+de+-

  • B  -+*abc+de

  • C  -+a*bc+de

  • D  abcde*++-

知识讲解 

 这里各种形式的互相转换,我推荐利用二叉树进行转换。

表达式与二叉树的关系

前缀表达式对应于二叉树的前序遍历

中缀表达式对应于二叉树的中序遍历

后缀表达式对应于二叉树的后序遍历

这样,你应该猜到了个大概,看个文章学习一下吧:利用二叉树将中缀表达式转换为后缀表达式_中缀表达式转后缀表达式二叉树 

答案解释

通过上面的知识,我们可以画出一棵树。如图所示:

按照先序读取,可得:
 -+a*bc+de。

因此,答案选C。


三.命题联接词

说实话,这道题错了,真的很不应该。。。

在( )的情况下,函数AVB运算的结果是逻辑“0”。
(题目来源CCF)

  • A   A和B全部是1

  • B   A和B任一是1

  • C   A和B全部是0

  • D   A和B任一是0

这里就牵扯到了一个十分重要的离散数学的东西——命题联接词

命题联接词符号范式例子
否定(非)¬¬Pp为真,¬p为假;p为假,¬p为真
合取(与)p∧qp为真,q为真,p∧q为真;
析取(或)p∨qp为假,q为假,p∨q为假

说句人话,就是:

非:将状态取反;

与:两者同为真,结果为真,否则为假;

或:两者同为假,结果为假,否则为真

按照上面的解释,可知此题选C.


四.高精度算法(加法)

题面

(高精度计算)由于计算机运算的数据范围表示有一定限制,如整型int表达范围是(-2^31~2^31-1),unsigned long(无符号整数)是(0~2^32-1),都约为几十亿,因此在计算位数超过十几位的数时,不能采用现有类型,只能自己编程计算。
高精度计算通用方法:高精度计算时一般用一个数组存储一个数,数组的一个元素对应于数的一位,将数由低位到高位依次存储在数组下标对应的由低到高的位置上。另外,申请数组大小时,一般考虑了最大的情况,在很多情况下表示有富裕,即高位有很多0,可能造成无效的运算和判断,因此一般利用一个整型数据存储该数的位数。下面的程序是一个高精度整数的加法运算,请补充完整程序。

 1   #include <iostream>
 2   #include <cstring>
 3   using namespace std;
 4
 5   struct HugeInt{
 6       int len; 
 7 	 int num[100001]; 
 8   };
 9   HugeInt a, b, w;
10   char c[100001],d[100001];
11   void Scan_HugeInt(){
12        cin>>c; 
13        cin>>d; 
14        a.len=strlen(c);
15        b.len=strlen(d);
16        for(int i=0: i<a.len; i++)
17                 ①; 
18        for(int i=0; i<b.len; i++)
19                 ②;
20    }
21    void Plus(){
22         w.len=max(a.len,b.len);
23         for(int i=1; i<=w.len; i++) ( 
24                  w.num[i] +=③; 
25                  w.num[i+1] +=④; 
26                  w.num[i]%=10; 
27         }
28         if(⑤) 
29                  w.len ++; 
30   }
31
32 int main() {
33    Scan_HugeInt();
34    Plus(); 
35    for(int i=w.len; i>=1; i--) 
36             cout <<w.num[i]; 
37    cout <<endl; 
38    return 0; 
39 }

(1)①处应填()。
A.a.num[i]=c[i]-‘0’
B.a.num[a.len-i]=c[i]-‘0’
C.a.num[a.len门=c[i]
D.a.num[门=c[i]

(2)②处应填( )。
A.b.num[i]=d[i]
B.b.num[b.len-i]=d[i]
C.b.num[b.len-i]=d[i]-‘0’
D.b.num[i]=d[i]-‘0’

(3)③处应填( )。
A.(a.num[i]+b.num[i])
B.(a.num[i]+b.num[i])%10
C.(a.num[i]%10+b.num[i]%10)
D.(a.num[i]+b.num[i]-10)

(4)④处应填( )。
A.w.num[i]/10
B.w.num[i]
C.w.num[i]%10
D.w.num[i]-10

(5)⑤处应填( )。
A.w.num[w.len+1]>=0
B.w.num[w.len+1]==0
C.w.num[w.len+1]!=0
D.w.num[w.len +1]>1

关于高精度算法,我曾经在一篇文章里提到过:高精度运算(加减乘除和乘方)

不想看那篇文章的,可以看我下面的解释。如果已经会了,可以跳过,直接进入本题的第三部分:答案解释。

知识讲解

所谓高精度,就是大数的运算,这个大数可能是要远远超过现有数据类型的最大范围。如果我们想进行这样的运算,就要掌握计算的原理——竖式运算。`

我们这里先简单考虑非负数的加法,竖式这么列对吧:

①逆序存储

我们如何储存过长的数呢?可以用数组存储。怎么才能将各个数位上的数放到数组里面呢?这里,我们可以使用字符串
我们使用逆序储存,这样会比较方便,后面可以在result数组中反向输出。


int a[241]=,b[241],result[242],l1=0,l2=0;
string c,d;
cin>>c>>d;
// 第一步读取整数
for(int i=c.size()-1;i>=0;i--){
	a[l1++]=c[i]-'0';
}
for(int i=d.size()-1;i>=0;i--){
	b[l2++]=d[i]-'0';
}

同时,这里l1表示第一个加数的长度,l2表示第二个加数的长度。

②模拟加法运算

接着,模拟运算:

	// 第二步加法计算
	int l=max(l1,l2)
	for(int i=0;i<l;i++){
		result[i]+=(a[i]+b[i])%10;
		result[i+1]+=(a[i]+b[i])/10;
	}

当我们进行加法运算时,每一位的结果是由两个部分组成的:当前位的数字和从低位“进”来的数字。例如,当我们计算23 + 18时,个位的结果是1,这个1就是从低位“进”来的,而2和3相加的结果是5,这个5就是当前位的数字。

在计算机中,当我们进行高精度计算时,通常会把每个数字拆分成多个位(如一个8位数字可以拆分成个位、十位、百位等),然后逐位进行加法运算。为了得到每个位的正确结果,我们需要考虑从低位“进”来的数字。

例如,如果我们有两个8位数字1234和5678,我们不能直接把它们相加,因为结果会超过8位。正确的做法是逐位进行加法运算:

1 + 6 = 7,没有进位,所以结果的个位就是7
2 + 7 = 9,进位1,所以结果的十位就是9 + 1 = 09
3 + 8 = 11,进位1,所以百位的结果是11 + 1 = 01
4 + 5 = 9,进位1,所以千位的结果是09 + 1 = 009

这样,我们就可以得到最终的结果:0097。

在上面的程序中,“进位”的思想体现在每次加法运算时都考虑了前一位的进位。通过这种方式,我们可以得到正确的高精度结果。

③反向输出:

for(int i=(x>y?x:y);i>=0;i--){
	cout<<result[i];
}

完整代码:

#include <iostream>
using namespace std;
int main(){
	// 高精度加法 240位内,调整数组大小可以扩大位数 
	int a[241]={},b[241]={},result[242]={},l1=0,l2=0;
	string c,d;
	cin>>c>>d;
	// 第一步读取整数
	for(int i=c.size()-1;i>=0;i--){
		a[l1++]=c[i]-'0';
	}
	for(int i=d.size()-1;i>=0;i--){
		b[l2++]=d[i]-'0';
	}
	int l=max(l1,l2); 
	// 第二步加法计算
	for(int i=0;i<l;i++){
		result[i]+=(a[i]+b[i])%10;
		result[i+1]+=(a[i]+b[i])/10;
	}
	for(int i=l;i>=0;i--){
		cout<<result[i];
	}
	return 0;
}

 答案讲解

这样,我们就可以做题了。

因为是逆序输入的,因此(1(2两题分别选B,C.

对于(3,常理来说,第三道题应该选B。但可以注意到,在这条语句进行之后,会进行mod 10 操作,因此这不就不需要mod 10了。所以,这里就只能选A或C了。但C冗余,因此选A。

根据公式,(4选A。

而(5,观察可知,下面的内容是 在 和的位数超过较大加数的位数的 情况下所执行的。所以这里的判断条件应该是,和的下一位数大于零。所以选C。

综上所述,此题答案应为 BCAAC


最后

祝愿顺利!

如果你只错了这几题甚至错得更少。

那就——

恭喜!有概率通过初赛~

考虑到初赛难度逐年增加,过线仍然存在风险,需要继续结合知识点题单查漏补缺,保证单选题,阅读程序和完善程序第一题的有效得分,在此基础上对阅读程序后两题和完善程序第二题进一步训练,尤其是近五年初赛中失分率最高的程序题,保证成绩的进一步提高。每周至少3次智能模考并对错题消化梳理,有利于维持备赛状态,赛前错题回顾和建立自信有利于比赛时的正常发挥,仍需努力,加油!

  • 11
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 19
    评论
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_L.Y.H._

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值