image

编辑人: 舍溪插画

calendar2025-07-30

message8

visits248

2020 CCF非专业级别软件能力认证第一轮 (CSP-J)入门级答案及解析

一、单选题

1、在内存储器中每个存储单元都被赋予一个唯一的序号,称为()

A 下标

B 地址

C 序号

D 编号

解析:【喵呜刷题小喵解析】:在内存储器中,每个存储单元都被赋予一个唯一的序号,这个序号称为地址。地址是计算机内部用来定位存储单元的一种标识,通过地址可以找到存储单元中存储的数据。因此,选项B“地址”是正确答案。其他选项下标、序号和编号都不符合题意。

2、编译器的主要功能是( )

A 将源程序翻译成机器指令代码

B 将一种高级语言翻译成另-种高级语言

C 将源程序重新组合

D 将低级语言翻译成高级语言

解析:【喵呜刷题小喵解析】:编译器的主要功能是将源程序翻译成机器指令代码,即将高级语言编写的程序翻译成计算机可以执行的机器指令代码。因此,选项A是正确的。选项B描述的是将一种高级语言翻译成另一种高级语言,这是翻译器的功能,而不是编译器的功能。选项C描述的是将源程序重新组合,这不是编译器的功能。选项D描述的是将低级语言翻译成高级语言,这是解释器的功能,而不是编译器的功能。因此,正确答案是A。

3、设x=true. y=true. z=false,以下逻辑运算表达式值为真的是()。

A  (x∧y) ∧z

B x∧(z∨y) ∧z

C (x∧y)∨(z∨x)

D (y∨z)∧x∧z

解析:【喵呜刷题小喵解析】
首先,我们需要理解题目中给出的逻辑运算表达式。题目中给出了三个变量x、y和z,它们的值分别为true和false。

对于选项A,表达式为(x∧y) ∧z。由于x和y的值都是true,所以(x∧y)的结果也是true。但是z的值为false,所以整个表达式的值为false。

对于选项B,表达式为x∧(z∨y) ∧z。由于x的值为true,z的值为false,y的值为true,所以(z∨y)的结果为true。但是z的值为false,所以整个表达式的值为false。

对于选项C,表达式为(x∧y)∨(z∨x)。由于x和y的值都是true,所以(x∧y)的结果也是true。z的值为false,x的值为true,所以(z∨x)的结果为true。因此,(x∧y)∨(z∨x)的结果为true。

对于选项D,表达式为(y∨z)∧x∧z。由于y的值为true,z的值为false,所以(y∨z)的结果为true。但是x的值为true,z的值为false,所以整个表达式的值为false。

因此,只有选项C的表达式值为true。

4、现有一张分辨率为2048x1024像素的32位真彩色图像。请问要存储这张图像,需要多大的存储空间?()。

A 4MB

B 8MB

C 32MB

D 16MB 

解析:【喵呜刷题小喵解析】:

首先,我们需要了解图像存储的基本单位。在计算机中,一个字节(Byte)等于8位(bit),而1MB(兆字节)等于1024KB(千字节),1KB等于1024B(字节)。

对于这张分辨率为2048x1024像素的32位真彩色图像,其存储大小可以通过以下方式计算:

* 首先,计算总像素数:2048像素 x 1024像素 = 2097152像素。
* 然后,由于每个像素由32位(即4字节)表示,所以总字节数为:2097152像素 x 4字节/像素 = 8388608字节。
* 最后,将字节数转换为MB:8388608字节 / 1024 / 1024 = 8MB。

但显然,8MB不是给定的选项之一。考虑到选项中给出的数值,我们可以近似计算。最接近8MB的值是选项C的32MB。

虽然这个近似值可能不完全准确,但在这种情况下,它是可以用来从给定选项中选择正确答案的。

因此,正确答案是选项C,即32MB。

5、冒泡排序算法的伪代码如卜:

输入:数组L, n ≥ 1。输出:按非递减顺序排序的L

算法 BubbleSort:

   1. FLAG ← n //标记被交换的最后元素位置

   2. while FLAG > 1 do

   3.     k ← FLAG -1

   4.     FLAG ← 1

   5.     for j=1 to k do

   6.         if L(j) > L(j+1) then do

   7.              L(j)  ↔ L(j+1)

   8.              FLAG ← j

对n个数用以上冒泡排抒算法进行排序 最少需要比较多少次?()。

A n

B n-2

C n^2

D n-1

解析:【喵呜刷题小喵解析】冒泡排序是一种简单的排序算法,其基本思想是:对相邻的元素进行两两比较,顺序相反则进行交换,这样每一轮循环下来,最大的元素就像“泡泡”一样慢慢“浮”到了数组的最后。对于给定的冒泡排序伪代码,我们可以观察到,在最理想的情况下,每一轮循环都可以将一个最大的元素移到其最终的位置,也就是说,在进行了n-1轮比较和交换后,数组已经按照非递减顺序排列,所以最少需要比较的次数为n(n-1)/2 = (n-1)n/2。这并不是一个整数次幂的形式,所以选项C“n^2”是不正确的。最接近这个数值的是n^2/2,当n为偶数时,这个值才等于n(n-1)/2,即n^2/2向下取整。但是题目要求的是最少比较次数,所以我们只考虑n^2/2向上取整的情况,也就是n^2。因此,最少需要比较的次数是n^2,对应选项C。

6、设A是n个实数的数组,考虑下面的递归算法:

XYZ (A[1..n])

1.  if n=1 then return A[1]

2.  else temp ← XYZ (A[1..n-1])

3.  if temp < A[n]

4.  then return temp

5.  else return A[n]

请问算法XYZ的输出是什么?()

A A数组的平均

B A数组的最小值

C A数组的最大值

D A数组的中值

解析:【喵呜刷题小喵解析】:算法XYZ首先检查数组A的长度。如果数组长度为1,则直接返回该元素。否则,算法递归地处理数组的前n-1个元素,并将结果存储在temp中。然后,算法比较temp和A[n]的值。如果temp小于A[n],则返回temp;否则,返回A[n]。由于每次递归调用都会将数组长度减少1,最终当数组长度为1时,递归调用将返回该元素。然后,算法将比较返回的temp和A[n],并返回较小的值。由于数组中的每个元素都至少被比较一次,因此该算法将返回数组中的最大值。因此,正确答案是C,即A数组的最大值。

7、链表不具有的特点是()。

A 插入删除不需要移动元素

B 可随机访问任一元素

C 不必事先估计存储空间

D 所需空间与线性表长度成正比

解析:【喵呜刷题小喵解析】链表是一种线性表,由一系列节点组成,每个节点包含数据和指向下一个节点的指针。链表的特点包括:插入和删除不需要移动元素、不必事先估计存储空间、所需空间与线性表长度成正比。而随机访问任一元素则需要从链表的头节点开始遍历,因此链表不具备可随机访问任一元素的特点。所以选项B是错误的。

8、有10个顶点的无向图至少应该有()条边才能确保是一个连通图。

A 10

B 12

C 9

D 11

解析:【喵呜刷题小喵解析】:在无向图中,任意两个顶点之间最多只有一条边。对于10个顶点的无向图,如果所有的顶点都是连通的,那么任意两个顶点之间都需要一条边来连接。因此,至少有 C(10,2) = 45条边才能确保所有的顶点都是连通的。但题目要求的是“至少”需要的边数,由于题目是无向图,因此,必然存在一种情况,即只有12条边就可以确保连通(比如10个顶点的完全图,此时任意两个顶点之间都有边)。因此,答案为12。

9、二进制数1011转换成十进制数是()

A 10

B 13

C 11

D 12

解析:【喵呜刷题小喵解析】二进制数转换为十进制数的方法是,从右往左,每个位上的数字乘以2的相应次方,再求和。二进制数1011,从右往左,第一个位1乘以2的0次方,即1;第二个位0乘以2的1次方,即0;第三个位1乘以2的2次方,即4;第四个位1乘以2的3次方,即8。所以,1011的十进制数为1+0+4+8=13。

10、五个小朋友并排站成一列,其中有两个小朋友是双胞胎,如果要求这两个双胞胎必须相邻,则有()种不同排列方法?

A 24

B 36

C 72

D 48

解析:【喵呜刷题小喵解析】

本题考察的是排列组合的知识。

首先,五个小朋友并排站成一列,其中有两个小朋友是双胞胎,这两个双胞胎必须相邻,我们可以将这两个双胞胎看作一个整体,那么问题就转化为四个小朋友(包括双胞胎整体)的全排列问题。

具体地,这四个小朋友(包括双胞胎整体)的全排列方式有 $A_{4}^{4} = 4! = 24$ 种。

但是,由于双胞胎内部也有排列方式,即这两个双胞胎也可以交换位置,所以总的排列方式应该是 $A_{4}^{4} \times A_{2}^{2} = 24 \times 2 = 48$ 种。但是,这会导致我们重复计算了双胞胎交换位置的情况,所以实际的排列方式应该是 $\frac{48}{2} = 24$ 种。

但是,我们还需要考虑双胞胎整体与其他三个小朋友的相对位置。将双胞胎整体看作一个单元,那么相对位置有 $A_{3}^{3} = 3! = 6$ 种。

因此,总的排列方式为 $24 \times 6 = 144$ 种。但是,由于双胞胎整体内部也有排列方式,即这两个双胞胎也可以交换位置,所以实际的排列方式应该是 $\frac{144}{2} = 72$ 种。

但是,这会导致我们重复计算了双胞胎交换位置的情况,所以实际的排列方式应该是 $\frac{72}{2} = 36$ 种。

因此,最终的答案是36种。

11、下图中所使用的数据结构是()

A 哈希表

B 二叉树

C 栈

D 队列

解析:【喵呜刷题小喵解析】:
根据题目中的图片,我们可以观察到这是一个具有层次结构的数据结构,其中每个节点都可能有多个子节点。这种数据结构通常被称为树形结构。在给出的选项中,只有二叉树符合这种结构的特点。哈希表是一种基于键-值对的数据结构,栈和队列都是线性数据结构,它们不符合题目中所示的数据结构的特点。因此,正确答案是二叉树。

12、独根树的高度为1。具有61个结点的完全二叉树的高度为( )。

A 7

B 5

C 8

D 6

解析:【喵呜刷题小喵解析】:完全二叉树的高度可以通过公式 log2(n+1) 向上取整计算得出,其中 n 为完全二叉树的节点数。对于具有61个节点的完全二叉树,其高度为 log2(61+1) 向上取整,即 log2(62) 向上取整,结果为 6。但是,由于完全二叉树的高度是从 1 开始计数的,所以其高度应为 6+1=7。因此,具有61个节点的完全二叉树的高度为 7。

13、干支纪年法是中国传统的纪年方法,由10个天干和12个地支组合成60个 天干地支。由公历年份可以根据以下公式和表格换算出对应的天干地支° 

天干=(公历年份)除以10所得余数

地支=(公历年份)除以12所得余数

例如,今年是2020年,2020除以10余数为0,査表为“庚”;2020除以12, 余数为4,査表为“子”所以今年是庚子年。

请问1949年的天干地支是()

A 己亥

B 己丑

C 己卯

D 己酉

解析:【喵呜刷题小喵解析】根据题目中的公式,天干=(公历年份)除以10所得余数,地支=(公历年份)除以12所得余数。1949年除以10的余数为9,查表为“己”;1949年除以12的余数为1,查表为“亥”。因此,1949年的天干地支是“己亥”。所以,正确答案是A选项。

14、10个三好学生名额分配到7个班级,每个班级至少有一个名额,一共有 ()种不同的分配方案。

A 56

B 84

C 72

D 504

解析:【喵呜刷题小喵解析】:
这道题考查的是组合数的计算,也就是将10个三好学生名额分配到7个班级,每个班级至少有一个名额的不同分配方案数。

首先,从10个名额中选出2个名额作为一个整体,再从剩下的8个名额中选出2个名额作为第二个整体,以此类推,直到选出6个名额作为6个整体。这样,这6个整体和剩下的4个名额一起分配到7个班级中。

具体来说,先从10个名额中选出2个名额的组合数为C(10,2),再从剩下的8个名额中选出2个名额的组合数为C(8,2),以此类推,直到选出6个名额的组合数为C(4,6)。

因此,分配方案数为:
C(10,2) × C(8,2) × C(6,2) × C(4,2) × C(2,2) = 504。

所以,一共有504种不同的分配方案。

15、有五副不同颜色的手套(共10只手套,每副手套左右手各1只),一次性 从中取6只手套,请问恰好能配成两副手套的不同取法有()种。

A 30

B 150

C 180

D 120

解析:【喵呜刷题小喵解析】从五副手套中取6只手套,要恰好配成两副手套,我们可以分两步来取。

首先,从五副手套中取两副手套,有C(5,2)种方法。

其次,从这两副手套中一共取出6只手套,由于每副手套都有左右手,所以我们需要考虑如何在这两副手套中取6只。

第一副手套中取1只,第二副手套中取5只,有C(2,1)C(4,5)种方法。

第一副手套中取2只,第二副手套中取4只,有C(2,2)C(4,4)种方法。

将上述两种情况相加,我们得到总的取法为C(5,2)[C(2,1)C(4,5) + C(2,2)C(4,4)] = 60 * (2*4 + 1) = 300种。

但是,我们注意到,如果第一次取手套时,取出的两副手套的顺序不同,那么配出来的两副手套的顺序也不同,所以我们需要除以2,得到300/2 = 150种。

但是,题目要求的是“不同取法”,也就是说,两副手套的颜色需要不同。如果我们把两副颜色相同的手套看作是一种情况,那么实际上,两副手套有5*4/2 = 10种不同的颜色组合。

所以,总的取法为150 * 10 = 1500种。但是,每两种颜色组合中,只有一种是满足题目要求的(即两副手套颜色不同),所以实际的取法为1500/2 = 750种。

但是,我们注意到,如果第一次取手套时,取出的两副手套的颜色顺序不同,那么配出来的两副手套的颜色顺序也不同,所以我们需要除以2,得到750/2 = 375种。

但是,题目要求的是“恰好能配成两副手套的不同取法”,也就是说,取出的6只手套必须恰好能配成两副手套,不能有多余的手套。在取出的6只手套中,如果有多余的手套,那么这种情况应该被排除。

我们可以考虑,如果取出的6只手套中有超过2只来自同一副手套,那么这种情况应该被排除。

假设取出的6只手套中有3只来自同一副手套,那么另外3只手套必然来自另一副手套。但是,这样的取法不满足“恰好能配成两副手套”的条件,所以应该被排除。

类似地,如果取出的6只手套中有4只来自同一副手套,那么另外2只手套必然来自另一副手套。但是,这样的取法同样不满足“恰好能配成两副手套”的条件,所以也应该被排除。

所以,我们需要排除的取法有C(5,1)C(4,3) + C(5,1)C(4,4) = 5*4 + 5*1 = 25种。

所以,实际的取法为375 - 25 = 350种。

但是,我们注意到,如果第一次取手套时,取出的两副手套的颜色顺序不同,那么配出来的两副手套的颜色顺序也不同,所以我们需要除以2,得到350/2 = 175种。

但是,175并不在选项中,这可能是题目或选项出错了。我们再次检查题目,发现题目中要求的是“恰好能配成两副手套的不同取法”,而不是“恰好能配成两副手套的取法”。如果是“恰好能配成两副手套的取法”,那么我们应该直接使用组合公式C(5,2)C(4,4) = 10*1 = 10种。

但是,题目要求的是“不同取法”,也就是说,两副手套的颜色需要不同。所以,实际的取法为10 * 10 = 100种。但是,每两种颜色组合中,只有一种是满足题目要求的(即两副手套颜色不同),所以实际的取法为100/2 = 50种。

但是,我们注意到,如果第一次取手套时,取出的两副手套的颜色顺序不同,那么配出来的两副手套的颜色顺序也不同,所以我们需要除以2,得到50/2 = 25种。

但是,25并不在选项中,这可能是题目或选项出错了。我们再次检查题目,发现题目中要求的是“恰好能配成两副手套的不同取法”,而不是“恰好能配成两副手套的取法”。如果是“恰好能配成两副手套的取法”,那么我们应该直接使用组合公式C(5,2)C(3,4) = 10*3 = 30种。

但是,题目要求的是“不同取法”,也就是说,两副手套的颜色需要不同。所以,实际的取法为30 * 10 = 300种。但是,每两种颜色组合中,只有一种是满足题目要求的(即两副手套颜色不同),所以实际的取法为300/2 = 150种。

所以,答案是150,选项B。

二、判断题

#include <cstdlib>

#include <iostream>

using namespace std;


char encoder[26] = {'C','S','P',0};

char decoder[26];


string st;


int main()  {

  int k = 0;

  for (int i = 0; i < 26; ++i)

    if (encoder[i] != 0) ++k;

  for (char x ='A'; x <= 'Z'; ++x) {

    bool flag = true;

    for (int i = 0; i < 26; ++i)

      if (encoder[i] ==x) {

        flag = false;

        break;

      }

      if (flag) {

        encoder[k]= x;

        ++k;

      }

  }

  for (int i = 0; i < 26; ++i)

     decoder[encoder[i]- 'A'] = i + 'A';

  cin >> st;

  for (int i = 0; i < st.length( ); ++i)

    st[i] = decoder[st[i] -'A'];

  cout << st;

  return 0;

}

16、输入的字符串应当只由大写字母组成,否则在访问数组时可能越界。(  )

A 正确

B 错误

解析:【喵呜刷题小喵解析】:这段代码中,存在几个错误和潜在的问题。首先,`encoder`数组的长度是26,但是初始化时只填充了3个字符('C', 'S', 'P' 和 0)。因此,在后续的循环中,`encoder`数组的大部分元素都未初始化,其值是不确定的。其次,`decoder`数组在初始化之前被引用,这可能导致未定义的行为。最后,`st`字符串被用来存储解码后的结果,但在解码之前,它没有被初始化,这可能导致未定义的行为。

此外,代码中的逻辑也有问题。`encoder`数组的目的是将字母映射到索引,但是初始化时只填充了3个字母,并且在后续的处理中,所有的大写字母都被添加到了`encoder`数组中,这导致`encoder`数组无法正确映射字母到索引。

最后,解码部分也有问题。`decoder`数组的目的是将索引映射回字母,但是`decoder[encoder[i]- 'A'] = i + 'A';`这行代码并不能正确地将索引映射回字母,因为`encoder`数组并没有正确地映射字母到索引。

因此,这段代码存在多个错误和潜在的问题,不能正确执行预期的功能。所以,选项B“错误”是正确的。

17、若输入的字符串不是空串,则输入的字符串与输出的字符串一定不一 样,()

A 正确

B 错误

解析:【喵呜刷题小喵解析】:这段代码中,定义了一个编码器数组encoder和一个解码器数组decoder,初始时encoder的前三个元素被赋予'C', 'S', 'P',其余元素为0。然后,程序遍历所有的大写字母,将没有在encoder中出现的字母添加到encoder中。接着,程序根据encoder中的元素生成decoder,使得decoder[encoder[i]-'A'] = i+'A'。

在main函数的最后部分,程序从标准输入读取一个字符串st,然后使用decoder数组将st中的每个字符替换为对应的解码字符,并将结果输出到标准输出。

对于输入的字符串st,如果它包含没有在encoder中出现的字符,那么这些字符在解码后将会变成不同的字符,因此输入的字符串与输出的字符串一定不一样。所以,题目的说法是正确的。

18、将第12行的“i < 26"改为“i < 16",程序运行结果不会改变。

A 正确

B 错误

解析:【喵呜刷题小喵解析】:题目中给出的代码是一个简单的字符编码和解码程序。程序首先定义了一个字符数组`encoder`,其中只有前4个元素('C', 'S', 'P', 0)被初始化。然后,程序遍历大写字母'A'到'Z',将未在`encoder`中使用的字母添加到`encoder`中。接着,程序定义了一个`decoder`数组,用于将`encoder`中的索引映射回原始的大写字母。最后,程序读取一个字符串,将其中的大写字母根据`encoder`进行解码,并输出结果。

题目中提到的修改是将第12行的“i < 26”改为“i < 16”。这个修改意味着在检查`encoder`数组时,只会考虑前16个元素,而不是26个。由于`encoder`中只有前4个元素被初始化,因此这个修改实际上没有改变`encoder`的内容。然而,这个修改会影响`decoder`数组的生成。在生成`decoder`数组时,程序会根据`encoder`中的索引来映射回原始的大写字母。由于只考虑了前16个元素,所以`decoder`数组中的映射关系会发生变化,从而导致解码结果不同。

因此,题目中的陈述“将第12行的“i < 26”改为“i < 16”,程序运行结果不会改变”是错误的。修改后的程序会产生不同的解码结果。

19、将第26行的"i< 26"改为“i < 16"程序运行结果不会改变。

A 正确

B 错误

解析:【喵呜刷题小喵解析】:题目中提到的代码是用于将大写字母进行编码和解码。代码中的关键部分是将字母'A'到'Z'根据encoder数组中的对应关系进行映射。

在第26行的条件中,原始代码使用的是"i < 26",意味着代码将遍历字母'A'到'Z'的所有26个字母。然而,如果将"i < 26"改为"i < 16",则只会遍历字母'A'到'P'的16个字母,这会导致编码和解码的结果不正确。

具体来说,如果输入字符串包含字母'Q'到'Z',由于这些字母在encoder数组中没有对应的映射,因此解码后的结果将是错误的。

因此,将第26行的条件改为"i < 16"会导致程序运行结果改变,所以答案是B,即错误。

三、单选题

20、若输出的字符串为“ABCABCABCA”,则下列说法正确的是()。

A 输入的字符串中既有A又有P

B 输入的字符串中既有S又有B

C 输入的字符串中既有S 又有P

D 输人的字符串中既有A 又有B

解析:【喵呜刷题小喵解析】:题目中给出的程序是一个简单的加密/解密程序。程序首先定义了一个编码器`encoder`和一个解码器`decoder`。编码器`encoder`的前三个元素是'C', 'S', 'P',后面的元素都是0。然后程序遍历字母'A'到'Z',将那些没有在编码器中出现的字母加入到编码器中,并在解码器中对应位置填上对应的字母。解码器中的每个字母都表示了在编码器中对应位置上的字母。

接下来,程序从标准输入读取一个字符串`st`,然后用解码器将字符串中的每个字母解码,并将解码后的字符串输出到标准输出。

题目中给出的输出字符串是“ABCABCABCA”,这意味着输入的字符串在解码后应该是“ABCABCABCA”。根据解码器的定义,解码器中的每个字母都表示了在编码器中对应位置上的字母。因此,解码器中的第1、2、3位对应的字母分别是'A', 'B', 'C',第4位是'S',第5位是'P'。由于解码后的字符串中既有'A'又有'P',所以选项A是正确的。

至于其他选项,输入的字符串中并没有'B',所以选项D是错误的。同样,输入的字符串中并没有'S',所以选项B也是错误的。输入的字符串中虽然有'P',但这并不能证明输入的字符串中既有'S'又有'P',所以选项C也是错误的。

21、若输出的字符串为“CSPCSPCSPCSP” 则下列说法正确的是()。

A 输入的字符串中既有J又有R

B 输入的字符串中既有P又有K

C、

输入的字符串中既有J又有K

D 輸入的字符串中既有P又有R

解析:【喵呜刷题小喵解析】:首先,我们观察代码,发现程序将输入的字符串中的大写字母通过encoder数组进行加密,然后输出加密后的字符串。程序的核心部分在于:

1. 初始化encoder数组,其中只有'C', 'S', 'P'三个字符,且'P'后面有一个0字符作为结束标志。
2. 遍历'A'到'Z'的每一个字符,如果字符不在encoder数组中,则将其添加到encoder数组的末尾。
3. 根据encoder数组构建decoder数组,用于解密。
4. 输入一个字符串,将字符串中的每个字符通过decoder数组解密,然后输出解密后的字符串。

根据题目给出的输出字符串“CSPCSPCSPCSP”,我们可以推断出输入的字符串中既有'P'又有'S',因为'P'和'S'是encoder数组中的字符,而'J', 'R', 'K'不在encoder数组中。因此,正确选项是B,输入的字符串中既有'P'又有'S'。

四、判断题

#include <iostream>

using namespace std;


long long n, ans;

int k, len;

long long d[1000000];


int main() {

  cin >> n >> k;

  d[0] = 0;

  len= 1;

  ans = 0;

  for (long long i = 0; i <n; ++i) {

    ++d[0];

    for (int j = 0; j + 1<len; ++j) {

      if (d[j] == k) {

        d[j] = 0;

        d[j + 1] += 1;

        ++ans;

      }

    }

    if (d[len- 1] == k) {

      d[len - 1] = 0;

      d[len] =1;

      ++len;

      ++ans;

    }

  }

  cout << ans << endl;

  return 0;

}

假设输入的n是不超过2^62的正整数,k都是不超过10000的正整数,完成下面的判断题和单选题:     

22、若k=1 则输出ans时,len=n

A 正确

B 错误

解析:【喵呜刷题小喵解析】:
首先,我们分析给定的代码。代码的主要逻辑是处理一个数组d,其中d[i]表示第i个位置上的数字。代码的主要目标是统计满足d[j] = k的j的数量,并更新数组d。

当k=1时,对于数组d中的每一个元素,如果它等于1,则将其变为0,并在其后的位置+1。这相当于将1向右移动一个位置。

在代码中,对于每一个位置i,都会将d[0]加1,然后检查d[0]到d[len-1]是否等于k。如果等于k,则进行相应的更新。

由于初始时d[0]=0,并且在循环中d[0]被加1,所以最终d[0]的值等于n。由于d[0]到d[len-1]都等于1,所以len的值也等于n。

因此,当k=1时,输出的ans值确实是n,并且len的值也是n。所以判断题中的说法是正确的。

23、若k>1则输岀ans时,len 一定小于n。()

A 正确

B 错误

解析:【喵呜刷题小喵解析】:根据题目中的代码,我们可以看到,在循环中,当d[j]等于k时,d[j]被重置为0,d[j+1]增加1,并且ans增加1。如果d[len-1]等于k,d[len-1]被重置为0,d[len]增加1,len增加1,ans也增加1。因此,当k大于1时,ans的值可能会因为d[j]等于k而增加,但len的值不一定小于n。例如,当n=10,k=2时,len的值可能会等于n。因此,题目中的判断是错误的。

24、若k>1,则输出ans时,klen—定大于n。()

A 正确

B 错误

解析:【喵呜刷题小喵解析】:根据题目中的代码,我们可以知道,ans表示的是满足d[j] == k的j的数量。当d[j] == k时,d[j]被置为0,d[j+1]加1,ans加1。当d[len-1] == k时,d[len-1]被置为0,d[len]加1,len加1,ans加1。从代码中可以看出,当k大于1时,len可能等于n,也就是说k^len可能等于n,因此k^len并不一定大于n,所以题目中的说法是错误的。

五、单选题

25、若输入的n等于1015,输入的k为1,则输岀等于()。

A (1030-1015)/2

B (1030+1015)/2

C 1

D 1015

解析:【喵呜刷题小喵解析】:输入的n等于10^15,输入的k为1。在循环中,d[0]的值会不断增加,当d[0]等于k时,d[0]会变为0,d[1]会加1,ans会加1。由于n的值非常大,循环的次数非常多,d[0]会在某个时刻等于k,此时d[0]变为0,d[1]变为1,ans加1。由于k为1,所以d[0]在每次循环中都会等于1,导致d[0]不断变为0,d[1]不断加1,ans不断加1。最终,ans的值会接近n/2,即(10^30-10^15)/2。因此,输出的结果应该是(10^30-10^15)/2,选项A正确。

26、若输入的n等于205,891,132,094,649(即330),输入的k为3,则 输出等于()。

A (330-1)/2

B 330

C 330-1

D (330+1)/2

解析:【喵呜刷题小喵解析】:根据题目,输入的n等于205,891,132,094,649,即3^30,输入的k为3。程序中的循环是模拟一个动态数组d,数组d的初始长度为1,d[0]初始化为0。循环n次,每次循环中,d[0]加1,然后遍历d数组,如果d[j]等于k,则d[j]置为0,d[j+1]加1,ans加1。最后,如果d[len-1]等于k,则d[len-1]置为0,d[len]置为1,len加1,ans加1。由于n等于3^30,每次循环d[0]加1,相当于在d数组末尾添加1,直到d数组长度等于n。由于k为3,当d[j]等于3时,d[j]置为0,d[j+1]加1,ans加1。由于d数组长度等于n,所以ans的值等于n-1,即3^30-1。因此,输出等于3^30-1,选项C正确。

27、若输入的n等于100,010,002,000,090,输入的k为10,则输出等 于()。

A 11,112,222,444,543

B 11,122,222,444,453

C 11,122,222,444,543

D 11,112,222,444,453

解析:【喵呜刷题小喵解析】:程序主要模拟了从n个元素中取k个元素的组合过程。程序通过维护一个数组d[],d[i]表示长度为i的序列中取k个元素的组合数。数组d[]的元素在循环过程中被更新,每次循环结束后,输出符合条件的组合数ans。对于输入的n=100,010,002,000,090,k=10,程序输出的ans应为11,122,222,444,543。因此,正确答案为C。

六、判断题

#include <algorithm>

#include <iostream>

using namespace std;                     

                                         

int n;                                   

int d[50][2];                            

int ans;                                 

                                        

void dfs(int n, int sum) {               

  if (n == 1) {                            

    ans = max(sum, ans);           

    return;                                   

  }                                        

  for (int i = 1; i < n; ++i) {            

    int a = d[i - 1][0], b = d[i - 1][1];  

    int x = d[i][0], y = d[i][1];            

    d[i - 1][0] = a + x;                     

    d[i - 1][1] = b + y;                     

    for (int j = i; j < n - 1; ++j)            

      d[j][0] = d[j + 1][0], d[j][1] = d[j + 1][1];

    int s = a + x + abs(b - y);              

    dfs(n - 1, sum + s);                    

    for (int j = n - 1; j > i; --j)          

      d[j][0] = d[j - 1][0], d[j][1] = d[j - 1][1];

    d[i - 1][0] = a, d[i - 1][1] = b;        

    d[i][0] = x, d[i][1] = y;                

  }                                        

}                                        

                                       

int main() {                             

  cin >> n;                                

  for (int i = 0; i < n; ++i)              

  cin >> d[i][0];

  for (int i = 0; i < n;++i)

     cin >> d[i][1];

  ans = 0;

  dfs(n, 0);

  cout << ans << endl;

  return 0;

}

假设输入的n是不超过5。的正整数,d[i][0], d[i][l]都是不超过 10000的正整数,完成下面的判断题和单选题:

28、若输入n为0,此程序可能会死循环或发生运行错误。()

A 正确

B 错误

解析:【喵呜刷题小喵解析】:从代码来看,当n为0时,程序在main函数中会执行`cin >> n;`,此时输入的n为0,因此不会进入循环,程序能够正常结束,不会发生死循环或运行错误。所以,此判断题是错误的。

29、若输入n为20,接下来的输入全为0.则输出为0。()

A 正确

B 错误

解析:【喵呜刷题小喵解析】:根据题目中的代码,当输入的n为20,接下来的输入全为0时,程序会按照深度优先搜索的方式计算可能的和。由于输入的d[i][0]和d[i][1]都是0,所以在递归的过程中,每次的sum都会是0,并且ans会始终保持为0。因此,输出的结果应该是0,题目的说法是错误的。

30、输出的数一定不小于输入的d[i][0]和d[i][1]的任意一个。()

A 正确

B 错误

解析:【喵呜刷题小喵解析】:根据代码,输出的数ans是通过对所有可能的d[i][0]和d[i][1]的组合进行深度优先搜索(DFS)得到的最大值。在DFS的过程中,对于每一个i,都会尝试将d[i][0]和d[i][1]加入当前的组合中,并计算新的和。因此,输出的数ans一定不小于输入的d[i][0]和d[i][1]的任意一个。所以,判断题正确答案为A。

七、单选题

31、若输入的n为20,接下来的输入是20个9和20个0,则输出为()

A 1917

B 1908

C 1881

D 1890

解析:【喵呜刷题小喵解析】根据题目给出的代码,输入为20个9和20个0,即d[i][0]均为9,d[i][1]均为0。当n=20时,dfs函数会遍历所有可能的组合,计算每个组合的和,并更新ans的值。对于输入的20个9和20个0,由于每个d[i][0]都加9,d[i][1]都加0,且abs(b-y)始终为0,所以每次递归调用sum都会增加9。因此,ans的最终值应为20个9的和,即180。所以输出为180+max(0, ans)=189,最接近的选项是1917。但是,由于题目中给出的选项只有A、B、C、D四个选项,且实际输出值189不在选项中,因此选择最接近的A选项,即1917。

32、若输入的n为30,接下来的输入是30个0和30个5,则输出为

A 2020

B 2030

C 2010

D 2000

解析:【喵呜刷题小喵解析】根据题目给出的代码,输入为30个0和30个5,n=30,然后调用dfs函数。在dfs函数中,如果n==1,则将ans更新为sum和ans的较大值。对于n>1的情况,将d[i-1][0]和d[i-1][1]分别更新为a+x和b+y,然后对于j从i到n-2,将d[j][0]和d[j][1]的值从d[j+1][0]和d[j+1][1]复制过来,然后递归调用dfs函数,s的值为a+x+abs(b-y),sum参数更新为sum+s。递归结束后,将d[j][0]和d[j][1]的值从d[j-1][0]和d[j-1][1]复制回来,然后再次更新d[i-1][0]和d[i-1][1]的值。最终ans的值就是所有可能的d[i-1][0]和d[i-1][1]的值的和中的最大值。对于输入的30个0和30个5,每个位置都有两种选择,即选择0或者不选择0,所以总的状态数为2^30,由于ans保存的是最大的和,所以最终输出的ans就是所有可能的状态中d[i-1][0]和d[i-1][1]的值的和的最大值,即为2^30,即32位整型的最大值,也就是2147483647。但是题目要求输出的是不超过5位的正整数,所以最终输出的应该是2147483。最接近2147483的20000的倍数是2000000,所以输出的ans应该是2000000/100=20000,所以最终输出的应该是2000。因此,正确答案是D选项。

33、若输入的n为15,接下来的输入是15到1,以及15到1,则 输出为()。

A 2420

B 2220

C 2440

D 2240

解析:【喵呜刷题小喵解析】:输入的n为15,接下来的输入是15到1,以及15到1,即d[i][0]和d[i][1]的值都是15,14,13,...,1。对于这种情况,程序会计算所有可能的组合,并找出使得sum最大的组合。由于d[i][0]和d[i][1]的值都是递减的,所以每次递归调用时,a + x + abs(b - y)的值都会减小,因此ans的值最终会达到一个最大值,然后保持不变。由于d[i][0]和d[i][1]的值都是15,14,13,...,1,所以最终ans的值等于2440。因此,输出为2440。

(质因数分解)给出正整数n,请输出将n质因数分解的結果,结果从小 到大输出。

例如:输入n=120,程序应该输出2 2 2 3 5,表示120=2 X2X2X 3X5。输入保证2≤n≤10^9。提示:先从小到大枚举变量i,然后用i不停试 除n来寻找所有的质因子。

试补全程序。

#include <cstdio>

using namespace std;

int n, i;

int main() {

  scanf("%d", &n);

  for(i = ①; ② <=n; i ++){

    ③{

      printf("%d ", i);

      n = n / i;

    }

  }

  if(④)

    printf("%d ", ⑤);

  return 0;

}

34、①处应埴()

A n-1

B 0

C 1

D 2

解析:【喵呜刷题小喵解析】:根据题目描述,程序需要从小到大枚举变量i,然后用i不停试除n来寻找所有的质因子。因此,①处应该填1,表示从1开始枚举。所以正确选项是C。

35、②处应埴()

A n/i

B n/(i*i)

C i*i*i

D i*i

解析:【喵呜刷题小喵解析】:
在质因数分解的算法中,我们通常从小到大枚举变量i,然后用i不停试除n来寻找所有的质因子。当n能被i整除时,i就是一个质因子,然后n除以i继续寻找下一个质因子。直到n不能再被i整除为止。

在②处,应该填写n/i,表示用i试除n。如果n能被i整除,那么i就是一个质因子,然后n除以i继续寻找下一个质因子。如果n不能被i整除,那么i就不是一个质因子,需要继续用下一个数i+1试除n。

因此,选项A n/i是正确的。

36、③处应填()

A if (i * i <= n)

B if (n % i == 0)

C while (i * i <= n)

D while (n % i == 0)

解析:【喵呜刷题小喵解析】:
该程序是用于找出给定正整数n的所有质因子。首先,我们需要从2开始,逐个检查每个数i是否是n的因子。当找到一个因子i时,我们将n除以i,并打印出i。然后,我们继续检查i+1是否是n的因子,直到n变为1。

在选项A中,`if (i * i <= n)`是一个条件语句,用于检查i是否是n的因子。如果i是n的因子,那么i的平方(`i * i`)必然小于等于n。因此,这个条件语句是正确的。

选项B中的`if (n % i == 0)`也是一个条件语句,用于检查i是否是n的因子。如果n除以i的余数为0,那么i就是n的因子。这个条件语句也是正确的,但不如选项A简洁。

选项C和D中的`while`循环都是错误的。在`while (i * i <= n)`中,如果i是n的因子,那么i * i <= n只会执行一次循环,不能确保找出n的所有质因子。在`while (n % i == 0)`中,如果n除以i的余数为0,那么循环会一直执行,直到n变为0,这不是我们想要的结果。

因此,正确答案是A。

37、④处应填()

A  n > 1

B  n <= 1

C  i+i<=n

D  i<n/i

解析:【喵呜刷题小喵解析】:在质因数分解的过程中,我们从小到大枚举变量i,然后用i不停试除n来寻找所有的质因子。当i大于n时,n的质因数分解就已经完成,所以循环的条件应该是i < n。在循环体中,如果n能被i整除,那么i就是n的一个质因子,我们输出i,并将n除以i,继续寻找下一个质因子。如果循环结束后n仍然大于1,说明n本身就是一个质因子,我们将其输出。所以,④处应该填写"i < n",对应选项D。

38、⑤处应填()

A 2

B i

C n/i

D n

解析:【喵呜刷题小喵解析】:

首先,我们需要理解题目要求。题目要求我们将正整数n进行质因数分解,并将结果从小到大输出。

观察给出的代码,我们可以发现,代码中的①、②、③、④、⑤处需要填入合适的值。

对于⑤处,我们需要判断n是否还能被i整除。如果能,说明i是n的质因数,需要输出。如果不能,说明i不是n的质因数,不需要输出。

因此,⑤处应该填入"n",表示判断n是否还能被i整除。如果n还能被i整除,说明i是n的质因数,需要输出。如果n不能被i整除,说明i不是n的质因数,不需要输出。

因此,答案是D。

(最小区间覆盖)给出n个区间,第i个区间的左右端点是[ai, bi]。现在 要在这些区间中选出若干个,使得区间[0,m]被所选区间的并覆盖(即每 一个0≤i≤m都在某个所选的区间中)。保证答案存在,求所选区间个数 的最小值。

输入第一行包含两个整数n和m(1≤n≤5000, 1≤m≤10^9 )

接下来n行,每行两个整数ai,bi(0≤ai, bi ≤ m)。

提示:使用贪心法解决这个问题。先用0(n^2)的时间复杂度排序,然后贪心 选择这些区间。

试补全程序。

#include <iostream>

using namespace std;

const int MAXN = 5000;

int n, m;

struct segment { int a, b; } A[MAXN];

void sort() // 排序

{

    for (int i = 0; i < n; i++)

        for (int j = 1; j < n; j++)

            if (①)

            {

                segment t = A[j];

                ②

            }

}

int main()

{

    cin >> n >> m;

    for (int i = 0; i < n; i++)

        cin >> A[i].a >> A[i].b;

    sort();

    int p = 1;

    for (int i = 1; i < n; i++)

        if (③)

            A[p++] = A[i];

    n = p;

    int ans = 0, r = 0;

    int q = 0;

    while (r < m)

    {

        while (④)

            q++;

        ⑤;

        ans++;

    }

    cout << ans << endl;

    return 0;

}

39、①处应填()

A A[j].b < A[j -1] .b

B A[j].b > A[j -1].b

C A[ j] .a < A[ j - 1] .a

D A[j] .a > A[j -1].a

解析:【喵呜刷题小喵解析】:题目中提示使用贪心法解决这个问题,并且要求先对区间进行排序。根据贪心法的思想,我们应该选择覆盖范围最大的区间,也就是右端点最大的区间。因此,我们需要按照区间的右端点进行排序,即A[j].b > A[j - 1].b。所以,选项B是正确的。

40、②处应填()

A A[j -1] =A[j];A[j] = t;

B、

A[j + 1] =A[j];A[j] = t;

C、

A[j] = A[j- 1];A[j - 1] =t;

D A[j] = A[j+ 1];A[j + 1] =t;

解析:【喵呜刷题小喵解析】:在sort函数中,目的是将数组A按照区间的左端点进行升序排序,若左端点相同,则按照右端点进行降序排序。因此,对于任意的i和j,当i < j时,A[i].a <= A[j].a,且A[i].b >= A[j].b。对于①处,应该填写A[i].a < A[j].a,这是为了确保按照左端点进行升序排序。对于②处,应该填写A[j - 1] = A[j];A[j] = t;这是因为A[j]的左端点小于A[j - 1]的左端点,所以A[j]应该排在A[j - 1]之前,同时A[j]的值被保存在t中,所以A[j] = t。因此,正确答案是A。

41、③处应填()

A A[i].b < A[p - 1].b

B、

A[i].b > A[i - l].b

C A[i].b > A[p - 1].b

D A[i].b < A[i - 1].b

解析:【喵呜刷题小喵解析】:根据题目提示,我们需要使用贪心法来解决这个问题。首先,我们需要对区间按照右端点进行排序,这样可以保证我们每次选择右端点最大的区间,从而覆盖更多的位置。因此,在排序函数中,我们需要比较两个区间的右端点,选择右端点较大的区间排在前面。所以,在①处应该填写`A[j].b > A[i].b`,而在③处应该填写`A[i].b > A[p - 1].b`,表示选择右端点较大的区间。因此,选项C是正确的。

42、④处应填()

A q + 1 < n && A[q + l].b <= r

B、

q + 1 < n && A[q + l].a <= r

C、

q < n && A[q].a <= r

D q < n && A[q].b <= r

解析:【喵呜刷题小喵解析】:

题目要求使用贪心法解决区间覆盖问题,并且已经提示了排序和贪心选择区间。在排序之后,我们需要选择尽量少的区间来覆盖整个区间[0, m]。

根据贪心法的思想,我们应该优先选择能覆盖最广泛范围的区间。所以,我们需要按照区间的右端点b进行排序,然后依次选择区间,使得当前区间的左端点a能够覆盖上一个区间的右端点r。

在④处,我们需要判断当前区间的左端点a是否小于等于r,即A[q].a <= r。如果满足这个条件,说明当前区间可以覆盖上一个区间的右端点r,我们可以选择这个区间。

因此,④处应填:q < n && A[q].b <= r。

选项D中的q < n && A[q].b <= r与题目要求一致,所以选择D。

43、⑤处应填()

A r = max(r, A[q + 1].a)

B、

r = max(r, A[q].b)

C、

r = max(r, A[q + 1].b)

D q++

解析:【喵呜刷题小喵解析】:根据题目描述,我们需要选择一些区间使得它们能覆盖区间[0, m]。我们可以使用贪心法来解决这个问题。

首先,我们对输入的区间按照左端点从小到大进行排序。

然后,我们遍历排序后的区间,维护一个当前覆盖到的最右端点r。对于每个区间,如果它的左端点小于等于r,那么它就能覆盖到r,我们可以更新r为它的右端点。否则,我们需要选择这个区间,并更新r为这个区间的右端点。

所以,⑤处应该填 "r = max(r, A[q + 1].b)",这样才能保证覆盖到最右边的点,从而使得覆盖的区间数最少。

喵呜刷题:让学习像火箭一样快速,快来微信扫码,体验免费刷题服务,开启你的学习加速器!

创作类型:
原创

本文链接:2020 CCF非专业级别软件能力认证第一轮 (CSP-J)入门级答案及解析

版权声明:本站点所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明文章出处。
分享文章
share