电话18065871965

邮箱qidianxingcheng@163.com

地址三明市三元区乾龙新村69幢B座2楼

2021CSP-J组初赛真题解析1-21

2022年9月15日 8,166

解析1

试题:1. 以下不属于面向对象程序设计语言的是( )。

A. C++

B. Python

C. Java

D. C

解析:

背景知识:

从描述客观系统的角度来看,程序设计语言可以分为:

(1) 面向过程语言

以“数据结构+算法”程序设计范式构成的程序设计语言,称为面向过程语言。代表语言有C、PASCAL等

(2) 面向对象语言

以“对象+消息”程序设计范式构成的程序设计语言,称为面向对象语言。比较流行的面向对象语言有 Delphi、Visual Basic、Java、C++、Python等。

知识点分类:

计算机基础知识-计算机语言

答案解析:

本题中A、B、C选项都是面向对象的程序设计语言,只有选项D中的C语言是面向过程的程序设计语言,所以正确答案应该选D。

解析2

试题:2. 以下奖项与计算机领域最相关的是( )。

A. 奥斯卡奖

B. 图灵奖

C. 诺贝尔奖

D. 普利策奖

解析:

背景知识:

奥斯卡奖

奥斯卡奖一般指奥斯卡金像奖。奥斯卡金像奖(Oscars),又名美国电影艺术与科学学院奖(Academy Awards,中文简称学院奖),是由美国电影艺术与科学学院主办的电影类奖项,创办于1929年。该奖项是美国历史最为悠久、最具权威性和专业性的电影类奖项,也是全世界最具影响力的电影类奖项。PS:听说过小金人吗?奥斯卡奖是一尊高10.25寸的男性人体塑像,铜像手握长剑、站在一盘电影胶片上,表面镀金,所以叫金像奖。

图灵奖

图灵奖(Turing Award),全称A.M.图灵奖(ACM A.M Turing Award),是由美国计算机协会(ACM)于1966年设立的计算机奖项,名称取自艾伦·麦席森·图灵(Alan Mathison Turing,1912年6月23日-1954年6月7日),英国数学家、逻辑学家,被称为计算机之父、人工智能之父。旨在奖励对计算机事业作出重要贡献的个人 。图灵奖对获奖条件要求极高,评奖程序极严,一般每年仅授予一名计算机科学家。图灵奖是计算机领域的国际最高奖项,被誉为“计算机界的诺贝尔奖”。

诺贝尔奖

诺贝尔奖(瑞典语:Nobel priset,英语:Nobel Prize)是指根据诺贝尔1895年的遗嘱而设立的五个奖项,包括:物理学奖、化学奖、和平奖、生理学或医学奖和文学奖,旨在表彰在物理学、化学、和平、生理学医学以及文学上“对人类作出最大贡献”的人士;以及瑞典中央银行1968年设立的诺贝尔经济学奖,用于表彰在经济学领域杰出贡献的人。

普利策奖

普利策奖(The Pulitzer Prizes),又称普利策新闻奖。是根据美国报业巨头约瑟夫·普利策(Joseph Pulitzer)的遗愿于1917年设立的奖项,后发展成为美国新闻界的最高荣誉奖。评选制度经过不断的完善后,普利策奖成为新闻领域的国际最高奖项,被誉为“新闻界的诺贝尔奖”。

知识点分类:

计算机基础知识-计算机通识知识

答案解析:

本题中A选项奖项是电影领域;C选项奖项是物理学、化学、和平、生理学、医学和经济学领域;D选项奖项是新闻界领域。只有选项B图灵奖是计算机领域的。所以正确答案应该选B。

真题解析3

3.目前主流的计算机储存数据最终都是转换成(  )数据进行储存。

A. 二进制

B. 十进制

C. 八进制

D. 十六进制

解析:

背景知识:

进制也就是进位计数制,是人为定义的带进位的计数方法。对于任何一种进制—X进制,就表示每一位上的数运算时都是逢X进一位。十进制是逢十进一,十六进制是逢十六进一,二进制就是逢二进一,以此类推,x进制就是逢x进位。

我们日常生活中有很多进制的例子,例如:

 一分钟六十秒,逢六十进一,就是六十进制;

 一天二十四小时,逢二十四进一,就是二十四进制;

 一星期七天,逢七进一,就是七进制;

 一年十二个月,逢十二进一,就是十二进制;

计算机采用二进制的原因:

1、技术实现简单:计算机是由逻辑电路组成,逻辑电路通常只有两个状态,开关的接通与断开,这两种状态正好可以用“1”和“0”表示。

2、简化运算规则:两个二进制数和、积运算组合各有三种,运算规则简单,有利于简化计算机内部结构,提高运算速度。

3、适合逻辑运算:逻辑代数是逻辑运算的理论依据,二进制只有两个数码,正好与逻辑代数中的“真”和“假”相吻合。

4、易于进行转换:二进制与十进制、八进制和十六进制数易于互相转换。

5、表示数据抗干扰能力强,可靠性高:因为每位数据只有高低两个状态,当受到一定程度的干扰时,仍能可靠地分辨出它是高还是低。

知识点分类:

计算机基础知识-进制与进制转换


答案解析:

本题中B选项十进制,由于人类解剖学的特点,双手共有十根手指,故在人类自发采用的进位制中,十进制是使用最为普遍的一种。C选项八进制和D选项十六进制,是因为他们与二进制之间转换很方便,而且与二进制比较更加方便阅读书写和记忆(例如IPv6的地址就是用十六进制表示的),所以引入。只有A选项二进制是广泛应用在计算机数据处理中的。所以正确答案应该选A。

真题解析8

8. 如果一棵二叉树只有根结点,那么这棵二叉树高度为1。请问高度为5的完全二叉树有(  )种不同形态?

A. 16

B. 15

C. 17

D. 32

解析:

背景知识:

二叉树:二叉树(Binary Tree)是n(n>=0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根节点和两棵互不相交的、分别称为根节点的左子树和右子树的二叉树组成。

满二叉树:在一棵二叉树中。如果所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树称为满二叉树。

完全二叉树:对一棵具有n个结点的二叉树按层编号,如果编号为i(1<=i<=n)的结点与同样深度的满二叉树中编号为i的结点在二叉树中位置完全相同,则这棵二叉树称为完全二叉树。

知识点分类:

程序设计基础知识-树

答案解析:

如下图所示,高度为5的满二叉树的第5层共有16个结点。要满足树的形态为完全二叉树,这棵树的1-4层不能有变化,最后一层的结点也一定要从左向右(16-31)排列,不能有间断。所以第5层最少有1个结点(16),最多有16个结点(16-31,满二叉树)。所以正确答案应该选A。

真题解析9

9. 表达式a*(b+c)*d的后缀表达式为(  ),其中”*”和”+”是运算符。

A. **a+bcd

B. abc+*d*

C. abc+d**

D. *a*+bcd

解析:

背景知识:

树的遍历是指访问树的每个结点,且每个结点仅被访问一次。二叉树的遍历可按二叉树的构成以及访问结点的顺序分为三种方式:先序遍历、中序遍历、后序遍历。

先序遍历:

遍历过程为:

  1. 访问根结点
  2. 先序遍历其左子树
  3. 先序遍历其右子树

先序遍历顺序=>  A  B  D  F  E  C  G  H  I

中序遍历:

遍历过程为:

  1. 中序遍历其左子树
  2. 访问根结点
  3. 中序遍历其右子树

中序遍历顺序=>   D  B  E  F  A  G  H  C  I

后序遍历:

其遍历过程为:

  1. 后序遍历其左子树
  2. 后序遍历其右子树
  3. 访问根结点

后序遍历顺序=>    D  E  F  B  H  G  I  C  A 


前缀表达式、中缀表达式、后缀表达式都是四则运算的表达方式,用以四则运算表达式求值。

中缀表达式:

中缀表达式就是常见的运算表达式,如(1+2)×3-4

前缀表达式:

前缀表达式又称波兰式,前缀表达式的运算符位于操作数之前,如× + 3 4 5

后缀表达式:

后缀表达式又称逆波兰表达式,与前缀表达式相似,只是运算符位于操作数之后,如1 2 + 3 × 4 –

知识点分类:

程序设计基础知识-树

答案解析:题干中表达式a*(b+c)*d是中缀表达式,转化成二叉树后,它是中序遍历的结果。后缀表达式,就是后序遍历该二叉树(如下图所示)

后序遍历顺序=>  a  b  c  +  *  d  *    

所得到的序列为:abc+*d*,所以正确答案应该选B。

真题解析10

10. 6个人,两个人组一队,总共组成三队,不区分队伍的编号,不同的组队情况有(   )种。

A. 10

B. 15

C. 30

D. 20

解析:

背景知识:

排列(Permutation):

从n个不同元素中,任取m(m≤n)个元素,按照一定的顺序排成一列,叫做从n个元素中取出m个元素的一个排列。

从n个不同元素中取出m(m≤n)个元素的所有排列的个数,叫做从n个不同元素中取出m个元素的排列数,用符号P(n,m)表示。

计算公式是:P(n,m)=n(n-1)(n-2)……(n-m+1)=n!/(n-m)!

n!表示n(n-1)(n-2)…1,规定0!=1。

例如:P(6,2) = 6!/(6-2)! = 6!/4! = 6*5*4*3*2*1/4*3*2*1 = 30

组合(Combination)

从n个不同元素中,任取m(m≤n)个元素并成一组,叫做从n个元素中取出m个元素的一个组合。

从n个不同元素中取出m(m≤n)个元素的所有组合的个数,叫做从n个不同元素中取出m个元素的组合数,用符号c(n,m)表示。

计算公式是:C(n,m)=P(n,m)/m!

n!表示n(n-1)(n-2)…1,规定0!=1。

例如:C(6,2) = P(6,2) / 2! = 6*5*4*3*2*1/2*1 = 15

知识点分类:

应用题求解-排列、组合

答案解析:

本题要求在6人中两人一组进行组队,共组成三队,则:

对于第一支队伍:

此时有6人可选,有C(6,2)=15 种组合

对于第二支队伍:

此时有4人可选,有C(4,2)=6 种组合

对于第三支队伍:

此时仅剩2人可选,只有1种组合

所以共有15*6*1=90种不同组合。

题目中要求不区分队伍的编号(这里可以假设6人编号分别为A,B,C,D,E,F),那么组合中相同队伍的情况会出现6次。

例如:组队组合是AB一队,CD一队,EF一队

那么AB,CD,EF AB,EF,CD CD,AB,EF CD,EF,AB  EF,AB,CD EF,CD,AB这6种组合,按照题目的要求都被视为同一种组队情况。

所以不区分队伍的编号,不同的组队情况有90/6=15

正确答案应该选B。

真题解析11

11. 在数据压缩编码中的哈夫曼编码方法,在本质是一种(   )的策略。

A. 枚举

B. 贪心

C. 递归

D. 动态规划

解析:

背景知识:

枚举算法:按照问题本身的性质,在一个有穷的可能的解的集合中,一一列举该问题所有可能的解,并在逐一列举的过程中,用题目给定的检验条件来判断每个可能解是否是问题的真正解,如果不是,就舍弃;如果是,就采纳。

贪心算法:贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择,以尽可能快得到更好的解。当求解进行到算法中某一步,无法继续前进时,算法就停止。

递归算法:通过重复将问题分解为同类的子问题而解决问题的算法,递归算法可以把模大的问题转化为规模小的相似的子问题来解决。

动态规划算法:通过将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。

知识点分类:

应用题求解-基础算法

答案解析:

哈夫曼提出构造最优前缀码的贪心算法,由此产生的编码方案称为哈夫曼编码。哈夫曼编码是广泛地用于数据文件压缩的十分有效的编码方法。其压缩率通常在20%~90%之间。哈夫曼编码算法用字符在文件中出现的频率表来建立一个用0,1串表示各字符的最优表示方式。哈夫曼编码是一个典型的使用贪心算法的例子,所以本题正确答案应该选B。

真题解析12

12. 由1, 1, 2, 2, 3这五个数字组成不同的三位数有(   )种。

A. 18

B. 15

C. 12

D. 24

解析:

背景知识:

排列(Permutation):

从n个不同元素中,任取m(m≤n)个元素,按照一定的顺序排成一列,叫做从n个元素中取出m个元素的一个排列。

从n个不同元素中取出m(m≤n)个元素的所有排列的个数,叫做从n个不同元素中取出m个元素的排列数,用符号P(n,m)表示。

计算公式是:P(n,m)=n(n-1)(n-2)……(n-m+1)=n!/(n-m)!

知识点分类:

应用题求解-排列

答案解析:

本题可以分两种情况进行考虑:

1.组成的三位数百位、十位和个位中没有重复的数字,如下图所示:

此时共有 P(3,3)=6 种三位数组合:

123, 132, 213, 231, 312, 321

2.组成的三位数百位、十位和个位中有重复的数字,如下图所示:

此时共有4*3=12种三位数组合:

112,121,211  113,131,311  

221,212,122  223,232,322

两种情况相加:6+12=18,不同的三位数组合共有18种,所以正确答案应该选A。

真题解析13

13. 考虑如下递归算法

solve(n)  
 if n <=1 return 1   
  else if n>=5 return n*solve(n-2)  
 else return n*solve(n-1)

则调用solve( 7 )得到的返回结果为( )

A. 105

B. 840

C. 210

D. 420

解析:

背景知识:

直接调用自己或通过一系列的调用语句间接地调用自己的函数,称为递归函数。递归通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,一个问题想要用递归的函数(方法)来解决,必须要符合两个条件:

1.可以把这个问题转化成一个新问题,而新问题的解法和原问题的解法完全相同,但问题的规模变小了

2.必须要有一个明确的递归结束条件(边界)

知识点分类:

C++程序设计-函数与递归

答案解析:

首先分析下题目所给的代码:

solve(n)  //定义名为solve的函数,参数为n 
if n <=1 return 1  //如果参数n小于或等于1,返回值为1  
else if n>=5 return n*solve(n-2)// 如果参数n大于或等于5,则返回值为:n*solve(n-2) 
 else return n*solve(n-1)//其他情况下,返回值为:n*solve(n-1)

本题中递归算法的递归函数调用过程如下图所示:

solve(7)=7*solve(5)

solve(5)=5*solve(3)

solve(3)=3*solve(2)

solve(2)=2*solve(1)

solve(1)= 1

所以solve(7)=7*5*3*2*1=210,正确答案应该选择C。

真题解析14

14. 以a为起点,对右边的无向图进行深度优先遍历,则b、c、d、e四个点中有可能作为最后一个遍历到的点个数为(  )。

A. 1

B. 2

C. 3

D. 4

解析:

背景知识:

从图中某一顶点出发依次访问图中其余顶点,且使每个顶点仅被访问一次的过程叫做图的遍历。

图的遍历分为深度优先遍历(DFS)和广度优先遍历(BFS)两种。

深度优先遍历(DepthFirstSearch)是从图中的某个顶点v出发,访问此顶点,然后从v的未被访问的邻接点出发深度优先遍历图,直到图中所有和v有路径相通的顶点都被访问到。若此时图中仍有未访问的顶点,则另选一个尚未访问的顶点作为新的源点重复上述过程,直至图中所有顶点均已被访问为止。

广度优先遍历(BreadthFirstSearch)从图中某个顶点v出发,首先访问出发点v,接着依次访问v的所有邻接点w1,w2,…,wt,然后再依次访问与wl,w2,…,wt邻接的所有未曾访问过的顶点。依此类推,直至图中所有和源点v有路径相通的顶点都已访问到为止。

知识点分类:

算法-图论算法-图的深度优先遍历算法

答案解析:

深度优先遍历算法的流程图如下:

本题中可能出现的深度优先遍历顺序有以下三种:

  1. =>a-b-d-c-e
  2. =>a-c-e-d-b
  3. =>a-c-d-b-e

有可能作为最后一个遍历到的点只有可能是e或者b,所以有可能作为最后一个遍历到的点的个数是2,所以正确答案应该选择B。

真题解析15

15. 有四个人要从A点坐一条船过河到B点,船一开始在A点。该船一次最多可坐两个人。已知这四个人中每个人独自坐船的过河时间分别为1, 2, 4, 8, 且两个人坐船的过河时间为两人独自过河时间的较大者。则最短(  )时间可以让四个人都过河到B点(包括从B点把船开回A点时间)。

A. 14

B. 15C. 16D. 17

解析:

背景知识:

本题目是信奥竞赛中经典的题目——过河问题,典型描述如下:

有X个人要过一条河,每个人过河都需要花费时间T。河边只有一艘船,该船一次最多可供两人一起划船过河。两个人划船过河所需的时间都取决于过河时间长的那个人。例如,A,B两人过河所需时间分别为Ta,Tb,那么,他们划一条船过河所需的时间为:max {Ta,Tb}(就是按照过河时间多的那个人花费的时间计算),求让所有人全部过河所用的最短时间是多少。

问题分析:

假设X=4,也就是有四个人要过河。设四人分别用a、b、c、d表示,并且所需时间Ta<Tb<Tc<Td,现在想让c、d过河,然后再让船回到过河前的位置,准备好继续送其他的人过河。那么有两种运载方式:

1.过河顺序为:ac、a、ad、a,时间消耗:t1=2Ta+Tc+Td

让所需时间最小的a来分别送c、d过河,因为a所需时间最少,所以每次a把船送回来所需的时间也是最少的。所以选择a来送有可能是最优方法。

2.过河顺序为:ab、a(b)、cd、b(a) 时间消耗:t2=Ta+2Tb+Td

如果c、d过河都需要很长的时间,那么就让他们一起过去,这样就可以很有效的去除掉相比较来说所需时间较小的c的过河时间,然后再让一个提前在对岸守好的b(之前由a送到对岸),再把船还回去。

以上两种是唯一比较有前途的送c、d过河的方式。

t1−t2=Ta+Tc−2Tb

显然,选择两种方案的哪一种,和Ta+Tc−2Tb的值有关。

在要过河人数n≥4的时候,先用上述两种方法中较好的一个,把最大的两个送过河。然后该问题就变成了:寻找把剩下的n-2个人送过河的最优策略。反复执行此策略,直到n=2时,两个人直接过去就行了。

知识点分类:

算法-基础算法-贪心法

答案解析:

本题中有4个人(假设a,b,c,d)过河,由题可知,过河时间分别为Ta =1,Tb =2,Tc =4,Td =8。

通过背景知识的分析可知,选用哪种过河顺序由t1-t2的值决定。计算t1-t2=Ta+Tc-2Tb=1+4-2*2=1>0

所以选择第二种过河顺序。ab、a(b)、cd、b(a)、ab 所需时间为:Ta+3*Tb+Td=1+3*2+8=15,所以正确答案应该选B。

真题解析16

#include <stdio.h>
using namespace std;
int n;int a[1000];
int f(int x)
{    int ret = 0;
    for (; x; x &=x-1) ret++;
    return ret;
 }
  int g(int x)
 {
     return x & -x;
 }
  int main()
 {
     cin >> n;
     for (int i = 0; i < n; i++)
 cin >> a[i];
     for (int i = 0; i < n; i++)
         cout << f(a[i]) + g(a[i]) << '';
     cout << endl;
     return 0;
 }

16. 输入的n等于1001时,程序不会发生下标越界(   )。

注:16-20题为阅读程序题型中的判断题,21题为阅读程序题型中的选择题。

解析:

背景知识:

数组是由一组具有相同数据类型的元素组成的集合。定义数组时需要指定这组元素的类型、数组名称和数组中包含元素的数量。

数组的定义

语法格式为:

数组类型  数组名[常量表达式];

例如:int  book[100];

其中数组类型就是数组中元素的数据类型,数组名是代表数组首地址的符号常量,常量表达式是数组中元素的个数,数组的下标从0开始。

数组的存储

用数组名加下标值就可以访问数组中对应的元素,下标值从0开始。对于一个具有n个元素的一维数组来说,它的下标值范围从0~n-1。

数组越界

对数组元素赋值或对数组元素进行引用时,一定要注意下标的值不能超过数组定义的范围,否则就会产生数组越界。

知识点分类:

C++程序设计-数组-数组定义、数组与数组下标的含义

答案解析:

首先分析下题目所给的代码:

#include <iostream>
using namespace std;
int n;//定义数组中元素的个数
int a[1000];//定义一个可以存储1000个元素的数组a 
int f(int x)  //定义函数f,对x与x-1循环做位运算,并返回循环执行的次数
 {
    int ret = 0;
    for (; x; x &=x-1) ret++;
    return ret;
 }
  int g(int x) //定义函数g,返回x与-x做位运算的值
 { 
    return x & -x;
 } 
int main( )
 { 
 cin >> n;   //输入数组元素的个数  
 for (int i = 0; i < n; i++)   cin >> a[i];//初始化数组a 
 for (int i = 0; i < n; i++)   //对数组的每个元素调用函数f和g,将结果相加并输出   
    cout <<f(a[i]) + g(a[i])<<" ";
  cout << endl;
  return 0;
}

代码第5行定义了数组的元素数量为1000,所以数组的下标值范围是0-999。

输入的n等于1001时,1001>999,程序将会发生下标越界。所以本题的描述是错误的,应该在括号内打×。

真题解析17

#include <stdio.h>
using namespace std;
int n;
int a[1000];
int f(int x)
{
    int ret = 0;
    for (; x; x &=x-1) ret++; 
   return ret;
 }
  int g(int x)
 { 
    return x & -x;
 } 
 int main()
 {  
   cin >> n; 
    for (int i = 0; i < n; i++)
 cin >> a[i];
     for (int i = 0; i < n; i++) 
        cout << f(a[i]) + g(a[i]) << ''; 
    cout << endl; 
    return 0;
 }

17. 输入的a[i]必须全为正整数,否则程序将陷入死循环。(  )

注:16-20题为阅读程序题型中的判断题,21题为阅读程序题型中的选择题。

解析:

背景知识:

位运算:

任何信息在计算机中都是采用二进制表示的,数据在计算机中是以补码形式存储的,位运算就是直接对整数在内存中的二进制位进行运算。根据NOI大纲要求,入门级阶段需要掌握的位运算有与(&)、或(|)、非(~)、异或(^)、左移(<<)和右移(>>)。

知识点分类:

C++程序设计-基本运算-位运算

答案解析:

首先分析下题目所给的代码:

#include <iostream>
using namespace std;
int n;//定义数组中元素的个数
int a[1000];//定义一个可以存储1000个元素的数组a 
int f(int x)  //定义函数f,对x与x-1循环做位运算,并返回循环执行的次数 
{
    int ret = 0; 
   for (; x; x &=x-1) ret++;
    return ret;
 }
  int g(int x) //定义函数g,返回x与-x做位运算的值 
{
     return x & -x;
 } 
int main( ) 
{
  cin >> n;   //输入数组元素的个数  
 for (int i = 0; i < n; i++) 
  cin >> a[i];//初始化数组a 
 for (int i = 0; i < n; i++)   //对数组的每个元素调用函数f和g,将结果相加并输出    
   cout <<f(a[i]) + g(a[i])<<" ";
  cout << endl;
  return 0;
}

根据背景知识中位运算的介绍,负数也是可以进行位运算的,所以本题的描述是错误的,应该在括号内打×。

真题解析18

18. 当输入“5 2 11 9 16 10”时,输出为“3 4 3 17 5” 。(  )

注:16-20题为阅读程序题型中的判断题,21题为阅读程序题型中的选择题。

解析:

背景知识:

位运算规则:

与(&):两个位都为1时,结果才为1

或(|): 两个位都为0时,结果才为0

(~):  0变1,1变0

异或(^):两个位相同为0,相异为1

知识点分类:

C++程序设计-基本运算-位运算

答案解析:

首先分析下题目所给的代码:

函数f(x)具体计算过程可以参考如下表格:

函数g(x)具体计算过程可以参考如下表格:

通过表格我们可以看出,程序最后的输出是:3 4 3 17 4


也可以通过编译运行程序进行验证:

我们输入:5 2 11 9 16 10,可以看到输出为:3 4 3 17 4。

而题目中给出的输出结果为“3 4 3 17 5”, 所以本题的描述是错误的,应该在括号内打×。

真题解析19

19. 当输入为”1 511998“时,输出为”18” 。(  )

注:16-20题为阅读程序题型中的判断题,21题为阅读程序题型中的选择题。

解析:

背景知识:

位运算规则:

与(&):两个位都为1时,结果才为1

或(|): 两个位都为0时,结果才为0

(~):  0变1,1变0

异或(^):两个位相同为0,相异为1

Population Count 算法:计算一个二进制数中1的个数。根据18题的分析和计算,我们可以看出,本题中的f函数实现的就是Population Count算法,计算二进制数中1的个数。

Lowbit函数:计算一个二进制数中最低位的1所对应的值。根据18题的分析和计算,我们可以看出,本题中的g函数实现的就是Lowbit函数的功能,计算二进制数中最低位的1所对应的值。

知识点分类:

C++程序设计-基本运算-位运算

答案解析:

首先分析下题目所给的代码:

我们把输入的十进制数511998转换为二进制数得到:

1111 1001 1111 1111 110

根据背景知识的分析

f(x)是计算二进制数中1的个数,所以f(x)=16;

g(x)是计算二进制数中最低位的1所对应的值,也就是计算0000 0000 0000 0000 010的值,所以g(x)=2

f(x)+g(x)=16 + 2 =18


也可以通过编译运行程序进行验证:

题目中给出的输出结果为“18”, 所以本题的描述是正确的,应该在括号内打√。

真题解析20

20. 将源代码中g函数的定义(13-16行)移到main函数的后面,程序可以正常编译运行。(   )

注:16-20题为阅读程序题型中的判断题,21题为阅读程序题型中的选择题。

解析:

背景知识:

函数定义:

返回类型  函数名([参数列表])

{

      函数体//执行语句

}

包括以下几个部分:

函数名:为函数所起的名字,必须是一个有效的C++标识符,给变量命名的规则同样也适用于给函数命名,但要注意,不可以使用C++的保留字作为函数名。

函数参数:包括形式参数和实际参数。

形式参数是用逗号分隔的变量说明列表,这些变量称为函数的形式参数。形式参数用于接收从函数调用程序传给这个函数的数据。

实际参数是用逗号分隔的表达式列表,其中每一个表达式称为实际参数。在函数调用时,需要将实际参数的值传送给对应位置的形式参数,因此它们两个参数的个数必须相同,而且数据类型也必须匹配。

函数体:函数体是使用花括号{  }限定的语句序列,分为说明部分和语句部分,用于描述这个函数所要执行的操作。说明部分用来对函数中使用的变量和函数作说明。语句部分由基本语句组成,函数的功能由函数体内的各个语句的执行来实现。

例如本题中的:

返回类型:函数可以将值发送回调用它的程序模块。返回类型是要发送回的值的数据类型。语法为:return 表达式;  

函数调用:

一个函数被定义后,程序中的其他函数就可以使用这个函数,这个使用的过程就称为函数调用。

函数名(实参列表);

函数声明:

调用函数之前先要声明函数原型。在主调函数中,或所有函数定义之前,按如下形式声明:

返回类型  函数名([参数列表]);

如果是在所有函数定义之前声明了函数原型,那么在本程序文件中任何地方都可以调用该函数。如果是在某个主调函数内部声明了被调用函数,那么该原型就只能在这个函数内部有效。

知识点分类:

C++程序设计-函数与递归-函数定义与调用,形参与实参

答案解析:

首先分析下题目所给的代码:

根据题意,我们将g函数的定义移到main函数的后面,并进行编译:

结果程序报错,提示g函数没有定义。这是因为函数必须先定义后调用。在main()函数中执行到调用g(a[i])时,此时g函数还没定义,所以编译出错。解决的方法是在程序的开始,所有函数定义之前先对g函数进行声明。

此时,编译通过。

通过上边的分析我们可以得出,如果要把g函数移动到main函数的后面,程序不可以正常编译, 所以本题的描述是错误的,应该在括号内打×。

真题解析21

21. 当输入为”2 -65536 2147483647”时,输出为(   )。

A. “65532 33”

B. “65552 32”

C. “65535 34”

D. “65554 33”

注:16-20题为阅读程序题型中的判断题,21题为阅读程序题型中的选择题。

解析:

背景知识:

数据类型:

C++程序设计语言中的数据类型类似于我们生活中使用的度量单位。例如一张桌子、两支钢笔、三本书,这里的单位“张”、“支”、“本”,其实就是人们在日常生活中使用的数据类型。程序设计中使用数据类型,主要的目的是让计算机知道应该如何处理数据。

整数型(Integer):整数型是程序设计语言中最常用的数据类型,顾名思义,整数型就是不含小数部分的数值,包括正整数和负整数。

位运算规则:

与(&):两个位都为1时,结果才为1

或(|): 两个位都为0时,结果才为0

(~):  0变1,1变0

异或(^):两个位相同为0,相异为1

Population Count 算法:计算一个二进制数中1的个数。根据18题的分析和计算,我们可以看出,本题中的f函数实现的就是Population Count算法,计算二进制数中1的个数。

Lowbit函数:计算一个二进制数中最低位的1所对应的值。根据18题的分析和计算,我们可以看出,本题中的g函数实现的就是Lowbit函数的功能,计算二进制数中最低位的1所对应的值。

知识点分类:

C++程序设计-基本数据类型-整数型

C++程序设计-基本运算-位运算

答案解析:

首先分析下题目所给的代码:

输入的第一个数字-65536转换为二进制为:

11111111 11111111 00000000 00000000共有16个1。所以f(x)=16,g(x)=65536,f(x)+g(x)=65552

输入的第二个数字:2147483647,这是C++整型变量的最大值即:01111111111111111111111111111111 共有31个1。所以:f(x)=31,g(x)=1,f(x)+g(x)=32


也可以通过编译运行程序进行验证:

所以本题正确答案应该选B。