C++洛谷初赛题解——2021

为了能顺利迎接CSP-JS的到来,又由于洛谷没有初赛题目的详细解析,所以“C++洛谷题解”专栏推出新的篇章——“C++洛谷初赛题解”!新的初赛题解与以往的题解格式有一定的差别,本人也是第一次做这种初赛的题解,所以初来乍到,请多指教。

好了,新的题解简介就介绍到这里。进入主题吧!


第一题

题目:

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

A. C++

B. Python

C. Java

D. C

解析:

这道题个人认为应该不用多说了吧,C++、Python、Java都属于面向对象设计语言,只有C是面向过程设计语言。面向对象设计语言更倾向于想让计算机做什么,而面向过程设计语言更倾向于想让计算机怎么做。上一张图吧:

答案:

D


 第二题

题目:

以下奖项与计算机领域最相关的是( )。

A. 奥斯卡奖

B. 图灵奖

C. 诺贝尔奖

D. 普利策奖

解析:

这道题也是送分题,但也详细的说一下吧:

  • 奥斯卡奖:奥斯卡奖应该所有人都知道,这是最高电影奖项
  • 图灵奖:这个不如奥斯卡奖有名气,这个是最高计算机奖
  • 诺贝尔奖:这个是最耳熟能详的奖项,这是最高科学奖
  • 普利策奖:这个奖项就相对陌生,这个是最高新闻奖

看到这都明白了吧,正确答案就是图灵奖。再来扩展一下,中国只有清华姚班、智班创始人——姚期智,与2000年获得图灵奖。

答案:

B


第三题

题目:

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

A. 二进制

B. 十进制

C. 八进制

D. 十六进制

解析:

又来了一道送分题,还是详细的说一下吧:

  • 二进制:由1和0组成的进制,是目前主流计算机所采用的进制
  • 十进制:由0~9十个数字组成,是目前人类最常用的进制
  • 八进制:由0~7八个数字组成,是大型机所采用的进制
  • 十六进制:由0~9和ABCDEF六个字母组成,是小众计算机所采用的进制,具有简洁易懂的特性

这里说一下大型机:

  • 巨型机:主要代表超级计算机,简称超算
  • 大型机:主要用于大型网站服务器
  • 中型机:主要用于中小型网站服务器
  • 小型机:主要用于学校、中小型企业的网络服务器
  • 微型机:主要用于学习、办公。我们手里的PC,笔电都属于微型机
  • 单机片:主要用于集成电路。树莓派就是单机片典型的例子
  • 工作站和终端:主要用于通讯,比如路由器

具体更详细的可以自行百度,这里就不再叙述了。

答案:

A


第四题

题目:

以比较作为基本运算,在 N 个数中找出最大数,最坏情况下所需要的最少的比较次数为 ( )。

A. N^{2}

B. N

C. N-1

D. N+1

解析:

从这道题开始就渐渐难起来了。但是有一点数学基础的人就知道,这种题就是概率问题。只要考虑最坏情况即可,最坏情况的次数就是N-1。

答案:

C


第五题

题目:

对于入栈顺序为 a, b, c, d, e 的序列,下列( )不是合法的出栈序列。

A. a, b, c, d, e

B. e, d, c, b, a

C. b, a, c, d, e

D. c, d, a, e, b

解析:

这道题还是比较简单的,只要学过栈就会做。我们一个个分析:

A:a入栈,a出栈,b入栈,b出栈,c入栈,c出栈,d入栈,d出栈,e入栈,e出栈。√

B:a入栈,b入栈,c入栈,d入栈,e入栈,e出栈,d出栈,c出栈,b出栈,a出栈。√

C:a入栈,b入栈,b出栈,a出栈,c入栈,c出栈,d入栈,d出栈,e入栈,e出栈。√

D:a入栈,b入栈,c入栈,c出栈,d入栈,d出栈,a出不了栈。⨉

栈作为线性数据结构中的线性表,最重要的特性是先进后出,或者说是后进先出,因此它又叫做先进后出表。栈底固定,而栈顶浮动;栈中元素个数为零时称为空栈。插入一般称为入栈,删除则称为出栈

答案:

D


第六题

题目:

对于有 n 个顶点、m 条边的无向连通图 (m>n),需要删掉( )条边才能使其成为一棵树。

A. n-1

B. m-n

C. m-n-1

D. m-n+1

解析:

出题人开始疯狂出数据结构的题了。这道题其实背下来就行了,删掉 m-n+1 条边才能成为一棵树。先说一下无向连接图吧:

无向连接图是指对图中任意顶点u,v,都存在路径使u、v连通。反之则有有向连接图。一个有向图D是指一个有序三元组(V(D),A(D),ψD),其中ψD)为关联函数,它使A(D)中的每一个元素(称为有向边或弧)对应于V(D)中的一个有序元素(称为顶点或点)对。放两张图就清楚了:

无向连接图:

有向连接图:

 说白了,没箭头的图就是无向连接图,有箭头的就是有向连接图。

答案:

D


第七题

题目:

二进制数 101.11 对应的十进制数是( )。

A. 6.5

B. 5.5

C. 5.75

D. 5.25

解析:

这道题就看监考严不严了。如果严就不太好弄,如果不是很严就很好弄。先说不难的方法吧:

在线进制转换用这个网站一下就出来了,结果是5.75

如果严...

分解二进制数

(101)₂.(11)₂

计算整数部分

(101)₂ = 1*2² + 0*2¹ + 1*2⁰ = (5)₁₀

计算小数部分

(11)₂ = 1*2⁻¹ + 1*2⁻² = (75)₁₀

合并

(5)₁₀.(75)₁₀ = (5.75)₁₀ = 5.75

电脑打数学真不舒服

答案:

C


第八题

题目:

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

A. 16

B. 15

C. 17

D. 32

解析:

又是一道数据结构的题,但这道题很简单。只需

2ⁿ⁻¹ = 2⁴ = 16

其中n就是层数

答案:

A


第九题

题目:

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

A. **a+bcd

B. abc+*d*

C. abc+d**

D. *a*+bcd

解析:

这道题需要搞清楚前缀表达式、中缀表达式、后缀表达式的相关知识。

中缀表达式

中缀表达式也就是我们平时数学里的运算,a*(b+c)*d就是一个中缀表达式。

3 + 4        5 - 6 * 7        (5 - 6) * 7        都是中缀表达式

前缀表达式

前缀表达式又称波兰表达式,大多数运算符都要放在左边。

+ 3 4        - 5 * 6 7        * - 5 6 7        都是前缀表达式

后缀表达式

后缀表达式又称逆波兰表达式,大多数运算符都放在右边

3 4 +        5 6 7 * -        5 6 - 7 *        都是后缀表达式

中缀表达式转前缀表达式

全体加括号

((a*(b+c))*d)

运算符放左括号外面

(*(a*+(b+c)d)

全体去括号(为了好看这里加了空格,实际上手写不用加)

* a * + b c d

中缀表达式转后缀表达式

全体加括号

((a*(b+c))*d)

运算符放右括号外面

((a(bc)+*)d)*

全体去括号

a b c + * d *

答案:

B


 第十题

题目:

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

A. 10

B. 15

C. 30

D. 20

解析:

这道题是一道纯纯的数学题,属于排列组合那里的知识(其实是考研的题)。这道题先放一边,先来说一下排列组合的相关知识:

排列组合是组合学最基本的概念。所谓排列,就是指从给定个数的元素中取出指定个数的元素进行排序。组合则是指从给定个数的元素中仅仅取出指定个数的元素,不考虑排序。排列组合的中心问题是研究给定要求的排列和组合可能出现的情况总数。 排列组合与古典概念论关系密切。

排列的定义:从n个不同元素中,任取m(m≤n,m与n均为自然数,下同)个不同的元素按照一定的顺序排成一列,叫做从n个不同元素中取出m个元素的一个排列;从n个不同元素中取出m(m≤n)个元素的所有排列的个数,叫做从n个不同元素中取出m个元素的排列数,用符号 A(n,m)A_{n}^{m}表示。计算公式:A_{n}^{m}=n(n-1)(n-2) (n-m+1)=\frac{n!}{(n-m)!}

组合的定义:从n个不同元素中,任取 m(m\leqslant n) 个元素并成一组,叫做从n个不同元素中取出m个元素的一个组合;从n个不同元素中取出m(m\leqslant n)个元素的所有组合的个数,叫做从n个不同元素中取出m个元素的组合数。用符号 C(n,m) 表示。

计算公式:C_{n}^{m}=\frac{A_{n}^{m}}{m!}=\frac{n!}{m!(n-m)!} ;C(n,m)=C(n,n-m),其中n\geqslant m

好了,排列组合的相关知识点就到这,现在看这道题,先列个式子:

C(6,2)×C(4,2)×C(2,2)÷A(3,3)
=(6×5÷2)×(4×3÷2)×(2×1÷2)÷(3×2×1)
=15×6×1÷6
=15

通过这个式子就可以得出最后的答案。这里还要说一下分组与分堆问题:

(1)均匀分组与不均匀分组

如果组与组之间的元素个数相同,则称为均匀分组;否则,称为不均匀分组。这道题是题目说道两人一队,所以是均匀分组。

(2)小组有名称或小组无名称

只是简单的分组,不考虑组别关系,则小组无名称;如果小组分为A组,B组,C组,种子队等,则小组有名称。如果均匀分组并且无名称,需要消序!消序即:除以堆数的全排列。而这道题题目说道不区分队伍的编号,即无名称小组。所以式子最后加上了A(3,3)用来消序。

答案:

B


第十一题

题目:

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

A. 枚举

B. 贪心

C. 递归

D. 动态规划

解析:

这是一道最最经典的贪心问题,这道题应该不会有人答错。

答案:

B


第十二题

题目:

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

A. 18

B. 15

C. 12

D. 24

解析:

这道题是暴力枚举的题,但是可以直接算:3*2*1+4*3=18。没错,就是这么简单。

答案:

A


第十三题

题目:

考虑如下递归算法:

 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

解析:

这道题有两种解题方法,分别为作弊法和画图法。先说我最熟悉的作弊法:

所谓作弊法就是把代码抄下来,自行编译。这里已经写好了,复制去吧

#include <bits/stdc++.h>
using namespace std;
int solve(int n){
    if(n<=1){
        return 1;
    }else if(n>=5){
        return n * solve(n - 2);
    }else{
        return n * (n - 1);
    }
}
int main()
{
    cout << solve(7);
    system("pause");
    return 0;
}

注意不要直接复制题目里的代码,代码并不是完整的!

画图法也就是正规比赛时的做法(因为正规考试时没有电脑),这道题怎么说呢?先放一张图吧

看上面的图:

 输入7,判断7大于5,所以减去2并重新递归

输入7-2即5,判断5等于5,所以减去2并重新递归

输入5-2即3,判断3小于5,即3的阶乘为6。开始递归

5*6等于30,用30重新递归

7*30等于210,递归结束。

答案:

C


第十四题

题目:

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

A. 1

B. 2

C. 3

D. 4

解析:

这道题考察的是深度优先遍历和广度优先遍历以及相关知识点。这里先说一下深度优先遍历和广度优先遍历的意思和区别:

深度优先遍历(Depth First Search, 简称 DFS) 与广度优先遍历(Breath First Search)是图论中两种非常重要的算法,生产上广泛用于拓扑排序,寻路(走迷宫),搜索引擎,爬虫等,也频繁出现在 leetcode,高频面试题中。主要思路是从图中一个未访问的顶点 V 开始,沿着一条路一直走到底,然后从这条路尽头的节点回退到上一个节点,再从另一条路开始走到底...,不断递归重复此过程,直到所有的顶点都遍历完成,它的特点是不撞南墙不回头,先走完一条路,再换一条路继续走。

树是图的一种特例(连通无环的图就是树),接下来我们来看看树用深度优先遍历该怎么遍历。

1、我们从根节点 1 开始遍历,它相邻的节点有 2,3,4,先遍历节点 2,再遍历 2 的子节点 5,然后再遍历 5 的子节点 9。

2、上图中一条路已经走到底了(9是叶子节点,再无可遍历的节点),此时就从 9 回退到上一个节点 5,看下节点 5 是否还有除 9 以外的节点,没有继续回退到 2,2 也没有除 5 以外的节点,回退到 1,1 有除 2 以外的节点 3,所以从节点 3 开始进行深度优先遍历,如下:

3、同理从 10 开始往上回溯到 6, 6 没有除 10 以外的子节点,再往上回溯,发现 3 有除 6 以外的子点 7,所以此时会遍历 7。

3、从 7 往上回溯到 3, 1,发现 1 还有节点 4 未遍历,所以此时沿着 4, 8 进行遍历,这样就遍历完成了。

完整的节点的遍历顺序如下(节点上的的蓝色数字代表):

相信大家看到以上的遍历不难发现这就是树的前序遍历,实际上不管是前序遍历,还是中序遍历,亦或是后序遍历,都属于深度优先遍历。

广度优先遍历,指的是从图的一个未遍历的节点出发,先遍历这个节点的相邻节点,再依次遍历每个相邻节点的相邻节点。上文所述树的广度优先遍历动图如下,每个节点的值即为它们的遍历顺序。所以广度优先遍历也叫层序遍历,先遍历第一层(节点 1),再遍历第二层(节点 2,3,4),第三层(5,6,7,8),第四层(9,10)。

深度优先遍历用的是栈,而广度优先遍历要用队列来实现,我们以下图二叉树为例来看看如何用队列来实现广度优先遍历。

动图如下:

说白了,深度优先遍历就是能深则深,广度优先遍历就是能广则广。

再回过头来看这道题,这道题要求的是深度优先遍历,即能深则深,这里就要分成两条路:第一条路是以左节点为中心遍历,第二条路是以右节点为中心遍历:

  • 第一条:a -- b,b -- d,d -- c,c -- e。结果是e
  • 第二条:a -- c,c -- e,e -- c,c -- d,d -- b结果是b

所以,共有两种,选择答案...

答案:

B


第十五题

题目:

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

A. 14

B. 15

C. 16

D. 17

解析:

这道题是一道经典的过河问题,考察的是贪心算法。要把性能好的人压榨干净。过程如下:

四个人分别命名为甲、乙、丙、丁。

  1. 先让甲和乙过河的B点,然后让甲把船开会A点。
  2. 再让丙和丁过河到B点,然后让在岸上的乙把船开回来。
  3. 最后让甲和乙过河到B点,四个人过河完毕!

他们需要的时间是:(2+1) + (8+2) + 2 = 15

分析一下这个式子,第一个括号里面的2是甲和乙过河的时间,1是甲把船开回来的时间;第二个括号里面的8是丙和丁过河的时间,2是乙把船开回来的时间;最后的2是甲乙二次过河的时间;加在一起的时间就是15

答案:

B


第十六题

题目:

二、阅读程序(程序输入不超过数组或字符串定义的范围;判断题正确填 √ ,错误填 × ;除特 殊说明外,判断题 1.5 分,选择题 3 分,共计 40 分)

#include <bits/stdc++.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;
    system("pause");
    return 0;
}

判断题

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

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

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

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

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

单选题

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

A. “65532 33”

B. “65552 32”

C. “65535 34”

D. “65554 33”

1. A. 正确        B. 错误

2. A. 正确        B. 错误

3. A. 正确        B. 错误

4. A. 正确        B. 错误

5. A. 正确        B. 错误

6. A. “65532 33”

   B. “65552 32”

   C. “65535 34”

   D. “65554 33”

 解析:

从这道题开始难度就开始“飙”了。我们就分解着做这道题吧

判断1:输入n的值是1001不会发生下标越界。这道题是一道妥妥的送分题,当然会发生越界。因为a数组才1000,题目来了一个1001当然会发生越界。

判断2:输入的a必须是正整数否则程序会越界。这也是一道送分题。输入0呢?输入负数的确有可能会越界。但是输入0不会呀。可0既不属于负数也不属于正数。

判断3:当输入5 2 11 9 16 10时程序输出3 4 3 17 5。这道题就不是送分题了,放一张图:

可以看到,如果输入5 2 11 9 16 10时g(x)的值是2 1 1 16 2,f(x)的值是 1 3 2 1 2,两数加在一起即f(x)+g(x)为3 4 3 17 4,并不是3 4 3 17 5,所以这道题选什么就出来了吧

判断4: 如果输入1 511998时会输出18。这道题也需要计算,511998的二进制是1111100111111111110,里面共有16个1;g(x)保留最后一个1,即00000000000000010,即二进制的2。16+2=18。所以答案为18

判断5:将源代码中 g 函数的定义(14-17 行)移到 main 函数的后面,程序可以正常编译运行。这明显是一道送分题。很明显移到主函数后面不可能能运行!

选择1:题太长了,就不复制了。第二个变量时int类型的最大值。2147483647改成2进制是01111111111111111111111111111111,共有一个0和31个1。f(x)是31,g(x)是1,所以答案是32。

答案:

B

B

B

A

B

B


第十七题

题目:

#include <bits/stdc++.h>
using namespace std;
char base[64];
char table[256];
void init()
{
    for (int i = 0; i < 26; i++)
    {
        base[i] = 'A' + i;
    }
    for (int i = 0; i < 26; i++)
    {
        base[26 + i] = 'a' + i;
    }
    for (int i = 0; i < 26; i++)
    {
        base[51 + i] = '0' + i;
    }
    base[62] = '+', base[63] = '/';
    for (int i = 0; i < 256; i++)
    {
        table[i] = 0xff;
    }
    for (int i = 0; i < 64; i++)
    {
        table[base[i]] = i;
    }
    table['='] = 0;
}
string decode(string str){
    string ret;
    int i;
    for (i = 0; i < str.size();i+=4){
        ret += table[str[i]] << 2 | table[str[i + 1]] >> 4;
        if(str[i+2]!='='){
            ret += (table[str[i + 1]] & 0x0f) << 4 | table[str[i + 2]] >> 2;
        }
        if(str[i+3]!='='){
            ret += table[str[i + 2]] << 6 | table[str[i + 3]];
        }
    }
    return ret;
}
int main(){
    init();
    cout << int(table[0]) << endl;
    string str;
    cin >> str;
    cout << decode(str) << endl;
    system("pause");
    return 0;
}

判断题

1.输出的第二行一定是由小写字母、大写字母、数字和“+”、“/”、“=”构成的字符串。( )

2.可能存在输入不同,但输出的第二行相同的情形。( )

3.输出的第一行为“-1”。( )

单选题

1.设输入字符串长度为 n,decode 函数的时间复杂度为( )

2.当输入为“Y3Nx”时,输出的第二行为()。

3.( 3.5 分) 当输入为“Y2NmIDIwMjE=”时,输出的第二行为( )。

1. A. 正确        B. 错误

2. A. 正确        B. 错误

3. A. 正确        B. 错误

4. A. O(\sqrt{n})O(n​)

    B. O(n)O(n)

   C. O(n \log n)O(nlogn)

   D. O(n^2)O(n2)

5. A. csp

   B. csq

   C. CSP

   D. Csp

6. A. ccf2021

   B. ccf2022

   C. ccf 2021

   D. ccf 2022

解析:

这道题和上一道题一样,还是分解着做。

判断1:这道题闭着眼就知道是错的,下面选择3输出的就有空格(虽然选择3还没做)。

判断2:这道题也是一道送分题,因为输入和输出的内容都是a~z,A~Z,'0'~'9',+,/,=时table才会是0~63,否则一律为0xff,所以有重合的可能。

判断3:这道题需要分析。通过分析能发现table[0]的值是0xff,因为是8位的char,所以是-1。

选择1:这道题是送分题,因为decode函数内有一个for循环,所以时间复杂度是O(n)。

选择2:这道题如果时间充沛可以尝试,否则也直接放弃。需要计算输入的数值,根据字典里的c s p q算出是csq。

选择3:这道题更难、更复杂。这道题如果没有极高的奥数及逻辑功底建议放弃。

 答案:

B

A

A

B

B

C


第十八题

题目:

#include <bits/stdc++.h>
using namespace std;
const int n = 100000;
const int N = n + 1;
int m;
int a[N], b[N], c[N], d[N];
int f[N], g[N];
void init()
{
    f[1] = g[1] = 1;
    for (int i = 2; i <= n; i++)
    {
        if (!a[i])
        {
            b[m++] = i;
            c[i] = 1, f[i] = 2;
            d[i] = 1, g[i] = i + 1;
        }
        for (int j = 0; j < m && b[j] * i <= n; j++)
        {
            int k = b[j];
            a[i * k] = 1;
            if (i % k == 0)
            {
                c[i * k] = c[i] + 1;
                f[i * k] = f[i] / c[i * k] * (c[i * k] + 1);
                d[i * k] = d[i];
                g[i * k] = g[i] * k + d[i];
                break;
            }
            else
            {
                c[i * k] = 1;
                f[i * k] = 2 * f[i];
                d[i * k] = g[i];
                g[i * k] = g[i] * (k + 1);
            }
        }
    }
}
int main()
{
    init();
    int x;
    cin >> x;
    cout << f[x] << " " << g[x] << endl;
    system("pause");
    return 0;
}

假设输入的 x 是不超过 1000 的自然数,完成下面的判断题和单选题:

判断题

1.若输入不为“1”,把第 13 行删去 不会 影响输出的结果。( )

2.( 2 分) 第 25 行的“f[i] / c[i * k]”可能存在无法整除而向下取整的情况。 ( )

3.( 2 分) 在执行完 init()后,f 数组不是单调递增的,但 g 数组是单调递增的。 ( )

单选题

1.init 函数的时间复杂度为( )。

2.在执行完 init()后,f[1], f[2], f[3] …… f[100]中有()个等于 2。

3.( 4 分) 当输入为“1000”时,输出为()。

1. A. 正确        B. 错误

2. A. 正确        B. 错误

3. A. 正确        B. 错误

4. A. O(n)O(n)

   B. O(n \log n)O(nlogn)

   C. O(n\sqrt{n})O(nn​)

   D. O(n!)O(n!)

5. A. 23

   B. 24

   C. 25

   D. 26

6. A. 15 1340

   B. 15 2340

   C. 16 2340

   D. 16 1340

 解析:

这道题依旧采用分解法。

判断1:因为程序后面没有f[1]和g[1]的地方,所以不影响

判断2:不可能存在,因为这是CCF的代码。

判断3:因为f数组不是,那么g数组也没有理由是单调的。

选择1:虽然有两个for循环,但是由于只有合数才会被记录,所以时间复杂度依旧是O(n)

选择2:f[i]的含义i有多少个因数,说白了就是问因数是2的有多少个,而只有质数/素数有因数2,即找100以内的质数,所以选择25。

选择3:1000以内因数个数和因数之和。

答案:

A

B

B

A

C

C


第十九题

题目:

(1)(Josephus 问题) 有 𝑛 个人围成一个圈,依次标号 0 至 𝑛 − 1。从 0 号开 始,依次 0 , 1 , 0 , 1 , … 交替报数,报到 1 的人会离开,直至圈中只剩下一个人。求最后 剩下人的编号。

试补全模拟程序。 

  1. ①处应填( )
    A.i < n
    B.c < n
    C.i < n- 1
    D.c < n-1

  2. ②处应填( )
    A.i % 2 == 0
    B.i % 2 == 1
    C.p
    D.!p

  3. ③处应填( )
    A.i++
    B.i = (i + 1) % n
    C.c++
    D.p ^= 1

  4. ④处应填( )
    A.i++
    B.i = (i + 1) % n
    C.c++
    D.p ^= 1

  5. ⑤处应填( )
    A.i++
    B.i = (i + 1) % n
    C.c++
    D.p ^= 1

  1. A B C D 
  2. A B C D
  3. A B C D
  4. A B C D
  5. A B C D

解析:

这种题并没有完美且正确的解析,所以程序填空题就不再提供解析了。

答案:

D

C

C

D

B


第二十题

题目:

( 2 ) (矩形计数) 平面上有 𝑛 个关键点,求有多少个四条边都和 x 轴或者 y 轴平行的矩 形,满足四个顶点都是关键点。给出的关键点可能有重复,但完全重合的矩形只计一 次。 

 试补全枚举算法。

  1. ①处应填 ( )
    A. a.x != b.x ? a.x < b.x : a.id < b.id
    B. a.x != b.x ? a.x < b.x : a.y < b.y
    C. equals(a, b) ? a.id < b.id : a.x < b.x
    D. equals(a, b) ? a.id < b.id : (a.x != b.x ? a.x < b.x : a.y < b.y)

  2. ②处应填 ( )
    A. i == 0 || cmp(A[i], A[i - 1])
    B. t == 0 || equals(A[i], A[t - 1])
    C. i == 0 || !cmp(A[i], A[i - 1])
    D. t == 0 || !equals(A[i], A[t - 1])

  3. ③处应填 ( )
    A. b - (b - a) / 2 + 1
    B. a + b + 1) >> 1
    C. (a + b) >> 1
    D. a + (b - a + 1) / 2

  4. ④处应填 ( )
    A. !cmp(A[mid], p)
    B. cmp(A[mid], p)
    C. cmp(p, A[mid])
    D. !cmp(p, A[mid])

  5. ⑤处应填 ( )
    A. A[i].x == A[j].x
    B. A[i].id < A[j].id
    C. A[i].x == A[j].x && A[i].id < A[j].id
    D. A[i].x < A[j].x && A[i].y < A[j].y

  1. A B C D
  2. A B C D
  3. A B C D
  4. A B C D
  5. A B C D

解析:

这种题并没有完美且正确的解析,所以程序填空题就不再提供解析了。

答案:

B

D

C

B

D


至此,CSP-J2021年版就做完了。这里提供一种做题技巧,很多省市属于“弱省”,几乎有分就过。即使像本人的省份河北这种要求高一点的省市,但也只要求40~50分即可通过。所以,只要能保证前面的选择全对,后面的程序阅读题和程序填空题蒙几个就可以了。But!如果你所在的省是“强省”最低要求也需要60分以上,就不能这样了。

posted @ 2022-07-19 19:46  GitTJBKBeta  阅读(866)  评论(0编辑  收藏  举报