NOIP 2017 普及组初赛

发布时间 2023-08-29 05:14:19作者: RonChen

T1

在 8 位二进制补码中,10101011 表示的数是十进制下的

  • A. 43
  • B. -85
  • C. -43
  • D. -84
答案

B

反码 +1 -> 补码
10101011 是补码,第一位是 0 则表示正数,1 表示负数
10101011-1=10101010,得出对应的反码,对应负数的绝对值的原码则为 01010101
1+0+4+0+16+0+64=85
因为是负数,所以是-85

练习:补码是 11101001,原数十进制是多少?

答案

-23

练习:-1 的补码是多少?(用 8 位二进制)

答案

11111111

练习:补码是 10011010,原数十进制是多少?

答案

-102

T2

计算机存储数据的基本单位是

  • A. bit
  • B. Byte
  • C. GB
  • D. KB
答案

B

计算机存储信息的基本单位是“字节”即 Byte
常用的单位还有 KB,MB,GB,TB 等
1 Byte = 8 bit
1 KB = 1024 Byte = \(2^{10}\) Byte ~ \(10^3\)
1 MB = 1024 KB = \(2^{20}\) Byte ~ \(10^6\)
1 GB = 1024 MB = \(2^{30}\) Byte ~ \(10^9\)
1 TB = 1024 GB = \(2^{40}\) Byte ~ \(10^{12}\)

T3

下列协议中与电子邮件协议无关的是

  • A. POP3
  • B. SMTP
  • C. WTO
  • D. IMAP
答案

C

WTO:World Trade Organization -> 世界贸易组织
POP3:Post Office Protocol 3 -> 邮局协议版本 3
SMTP:Simple Mail Transfer Protocol -> 简单邮件传输协议
IMAP:Internet Mail Access Protocol -> 交互式邮件存取协议

T4

分辨率为 800×600、16 位色的位图,存储图像信息所需的空间为

  • A. 937.5 KB
  • B. 4218.75 KB
  • C. 4320 KB
  • D. 2880 KB
答案

A

16 位色图的意思是用 16 位二进制表示一个颜色,一个像素点消耗 2 Byte

\(\large \frac{800 \times 600 \times 2}{1024} = 937.5 KB\)

T5

计算机应用的最早领域是

  • A. 数值计算
  • B. 人工智能
  • C. 机器人
  • D. 过程控制
答案

A

计算机是为了计算的需要而发明的,第一代电子计算机是为计算弹道而设计的,所以计算机最早的应用领域是数值计算

T6

下列不属于面向对象程序设计语言的是

  • A. C
  • B. C++
  • C. Java
  • D. C#
答案

A

面向对象程序设计(英语:Object-oriented programming,缩写:OOP)是一种具有对象概念的编程范式,同时也是一种程序开发的抽象方针。它可能包含数据、特性、代码与方法。对象则指的是类(class)的实例。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性,对象里的程序可以访问及经常修改对象相关连的数据。在面向对象程序编程里,计算机程序会被设计成彼此相关的对象。

面向对象程序设计可以看作一种在程序中包含各种独立而又互相调用的对象的思想,这与传统的思想刚好相反:传统的程序设计主张将程序看作一系列函数的集合,或者直接就是一系列对电脑下达的指令。面向对象程序设计中的每一个对象都应该能够接受数据、处理数据并将数据传达给其它对象,因此它们都可以被看作一个小型的“机器”,即对象。目前已经被证实的是,面向对象程序设计推广了程序的灵活性和可维护性,并且在大型项目设计中广为应用。此外,支持者声称面向对象程序设计要比以往的做法更加便于学习,因为它能够让人们更简单地设计并维护程序,使得程序更加便于分析、设计、理解。

重要的面向对象编程语言包含Common Lisp、Python、C++、Objective-C、Smalltalk、Delphi、Java、Swift、C#、Perl、Ruby、JavaScript 与 PHP 等。

T7

NOI 的中文意思是

  • A. 中国信息学竞赛
  • B. 全国青少年信息学奥林匹克竞赛
  • C. 中国青少年信息学奥林匹克竞赛
  • D. 中国计算机协会
答案

B

NOI 全称 National Olympiad in Informatics,意思是全国青少年信息学奥林匹克竞赛。

赛事简介:全国青少年信息学奥林匹克竞赛(NOI)是由国家教育部、中国科协批准,中国计算机协会主办的一项面向全国青少年的信息学竞赛和普及活动。也是与联合国教科文组织提倡的国际信息学奥林匹克竞赛同步进行的一项竞赛活动。自 1984 年至今,在国内包括香港、澳门组织竞赛活动。

T8

2017 年 10 月 1 日是星期日,1999 年 10 月 1 日是

  • A. 星期三
  • B. 星期日
  • C. 星期五
  • D. 星期二
答案

C

10 月 1 日是周日,则 10 月 8 日也是周日。

1999 -> 2017 共 18 年,平年每年 365 天,闰年每年 366 天,这期间共 5 个闰年,分别是 2000、2004、2008、2012、2016,(18 * 365 + 5) / 7 = 939 余 2,往回推 2 天,所以是周五。

T9

甲、乙、丙三位同学选修课程,从 4 门课程中,甲选修 2 门,乙、丙各选修 3 门,则不同的选修方案共有( )种

  • A. 36
  • B. 48
  • C. 96
  • D. 192
答案

C

\(C_4^2 \times C_4^3 \times C_4^3 = 96\)

T10

设 G 是有 n 个节点、m 条边(n≤m)的连通图,必须删去 G 的( )条边,才能使得 G 变成一棵树

  • A. m - n + 1
  • B. m - n
  • C. m + n + 1
  • D. n - m + 1
答案

A

自由树(free tree)就是连通无回路图
无回路但不一定连通的图称为森林(forest)
树的边数总是比它的顶点数少 1
回路(loop):起点和终点是同一顶点,长度大于 0,同一条边不会包含两次及以上
image

T11

对于给定的序列 \({a_k}\),我们把 \((i,j)\) 称为逆序对当且仅当 \(i<j\)\(a_i > a_j\),那么序列 1,7,2,3,5,4 的逆序对数为

  • A. 4
  • B. 5
  • C. 6
  • D. 7
答案

B

T12

表达式 a * (b + c) * d 的后缀形式是

  • A. a b c d * + *
  • B. a b c + * d *
  • C. a * b c + * d
  • D. b + c * a * d
答案

B

后缀表达式不包括括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不需要再考虑运算符的优先规则)

运用后缀表达式进行计算的具体做法:
建立一个栈 S,从左向右读表达式,如果读到操作数就将它压入栈 S 中,如果读到 n 元运算符(即需要参数个数为 n 的运算符)则取出由栈顶向下的 n 项进行运算,再将运算的结果代替原栈顶的 n 项,压入栈 S 中。如果后缀表达式未读完,则重复上面过程,最后输出栈顶的数值则结束

T13

向一个栈顶指针为 hs 的链式栈中插入一个指针 s 指向的结点时,应执行

  • A. hs->next = s;
  • B. s->next = hs; hs = s;
  • C. s->next = hs->next; hs->next = s;
  • D. s->next = hs; hs = hs->next;
答案

B

s 插入后成为栈顶,s 的 next 就是原来的 hs,栈顶指针重新赋值为 s
image

T14

若串 S = "copyright",其子串的个数是

  • A. 72
  • B. 45
  • C. 46
  • D. 36
答案

C

子串:串中任意个连续的字符组成的子序列称为该串的子串(备注:空串属于子串

n 个字符构成的字符串,假设每个字符都不一样,有多少个子串?

  • 包含 1 个字符的子串共 n 个
  • 包含 2 个字符的子串共 n-1 个
  • 包含 3 个字符的子串共 n-2 个
    ……
  • 包含 n 个字符的子串共 1 个

综上所述,子串个数共:1+2+3+...+n+1(空串)=n(n+1)/2+1

练习:字符串 www.qq.com 所有非空子串(两个子串如果内容相同只算一个)的个数是

答案

50

要考虑内容相同,计算方法为总个数减去重复个数

10(10+1)/2=55,减去重复:2 个 w,1 个 ww,1 个 q,1 个 .,所以共 55-5=50 个

T15

十进制小数 13.375 对应的二进制数是

  • A. 1101.011
  • B. 1011.011
  • C. 1101.101
  • D. 1010.01
答案

A

整数部分:\(13=8+4+1=2^3+2^2+2^0=(1101)_2\)

小数部分:\(0.375=2^{-2}+2^{-3}=(0.011)_2\)
2 的 -1 次方是 0.5
2 的 -2 次方是 0.25
2 的 -3 次方是 0.125

T16

对于入栈顺序为 a, b, c, d, e, f, g 的序列,下列不可能是合法出栈序列的是

  • A. a, b, c, d, e, f, g
  • B. a, d, c, b, e, g, f
  • C. a, d, b, c, g, f, e
  • D. g, f, e, d, c, b, a
答案

C

栈的进出规则是先进后出,模拟 C 选项:

  1. a 进 a 出
  2. 为了第二个是 d 出栈,d 要先进栈,因为入栈顺序是 b c d,所以 d 出栈后,栈里还剩下 bc,b 在 c 下面,不可能在 c 前出栈

T17

设 A 和 B 是两个长为 n 的有序数组,现在需要将 A 和 B 合并成一个排好序的数组,任何以元素比较作为基本运算的归并算法在最坏情况下至少要做多少次比较?

  • A. \(n^2\)
  • B. \(n \log n\)
  • C. \(2n\)
  • D. \(2n - 1\)
答案

D

归并算法过程:

  • 先在 A、B 数组中各取第一个元素进行比较,将小的元素放入 C 数组
  • 取小的元素所在数组的下一个元素与另一数组中上次比较后较大的元素比较,重复上述比较过程,直到某个数组被先排完
  • 将另一个数组剩余元素抄入 C 数组,合并排序完成

A:1、4、6
B:2、5、8
1 与 2 进行比较 -> C:1
2 与 4 进行比较 -> C:1、2
4 与 5 进行比较 -> C:1、2、4
5 与 6 进行比较 -> C:1、2、4、5
6 与 8 进行比较 -> C:1、2、4、5、6
将 8 并入 -> C:1、2、4、5、6、8

T18

从哪年开始,NOIP 竞赛将不再支持 Pascal 语言

  • A. 2020
  • B. 2021
  • C. 2022
  • D. 2023
答案

C

CCF关于NOI系列赛事程序设计语言变更的公告

T19

一家四口人,至少两个人生日属于同一月份的概率是(假设每个人生日属于每个月份的概率相同且不同人之间相互独立)

  • A. 1/12
  • B. 1/144
  • C. 41/96
  • D. 3/4
答案

C

至少两个人生日属于同一月份,则有可能两个人同属一个月份,也有可能三个人同属一个月份,很有可能四个人同属一个月份

一家四口生日的情况总数为:\(12 \times 12 \times 12 \times 12=20736\)
一家四口均不在同一月份的情况总数为:\(12 \times 11 \times 10 \times 9 = 11880\)
一家四口至少两个人生日属于同一月份的总数为:\(20736 - 11880 = 8856\)
\(8856 / 20736 = 41 / 96\)

T20

以下和计算机领域密切相关的奖项是

  • A. 奥斯卡奖
  • B. 图灵奖
  • C. 诺贝尔奖
  • D. 普利策奖
答案

B

奥斯卡奖:奥斯卡金像奖,是每年由美国电影艺术与科学学院组织与颁发,旨在鼓励过去一年间优秀电影创作、发展奖励活动,不仅是美国电影业界年度最重要活动,亦是目前最受世界瞩目的电影奖之一。

图灵奖:由美国计算机协会(ACM)于 1966 年设立,专门奖励那些对计算机事业做出重要贡献的个人。其名称取自计算机科学的先驱——英国科学家艾伦·麦席森·图灵(Alan M. Turing)。由于图灵奖对获奖条件要求极高,因此它是计算机界最负盛名、最崇高的一个奖项,有“计算机界的诺贝尔奖”之称。

诺贝尔奖:以瑞典著名的化学家阿尔弗雷德·贝恩哈德·诺贝尔(Alfred Bernhard Nobel)的部分遗产(3100 万瑞典克朗)作为基金在 1895 年创立。在世界范围内,诺贝尔奖通常被认为是所颁奖的领域内最重要的奖项。诺贝尔奖最初分设物理(Physics)、化学(Chemistry)、生理学或医学(Physiology or Medicine)、文学(Literature)、和平(Peace)等五个奖项。于 1901 年首次颁发。

普利策奖:1917 年根据美国报业巨头约瑟夫·普利策(Joseph Pulitzer)的遗愿设立,二十世纪七八十年代已经发展成为美国新闻界的意向最高荣誉奖,现在,不断完善的评选制度已使普利策奖成为全球性的一个奖项。约翰·肯尼迪(John Kennedy,1917 年 5 月 29 日 ~ 1963 年 11 月 22 日)是唯一获得这个奖项的美国总统。

T21

一个人站在坐标 (0,0) 处,面朝 x 轴正方向。第一轮,他向前走 1 单位距离,然后右转;第二轮,他向前走 2 单位距离,然后右转;第三轮,他向前走 3 单位距离,然后右转……他一直这么走下去。请问第 2017 轮后,他的坐标是
image

答案

(1009,1008)

第 1、5、9 轮在第一象限,2017/4=504 余 1,所以第 2017 轮后在第一象限

第 1 轮(1/4=0 余 1)-> (1,0)
第 5 轮(5/4=1 余 1)-> (3,2)
第 9 轮(9/4=2 余 1)-> (5,4)
第 13 轮(13/4=3 余 1)-> (7,6)
……

T22

如下图所示,共有 13 个格子。对任何一个格子进行一次操作,会使得它自己以及与它上下左右相邻的格子中的数字改变(由 1 变 0,或由 0 变 1)。现在要使得所有的格子中的数字都变为 0,至少要多少次操作
image

答案

image

T23

#include <iostream>
#include <string>
using namespace std;
int main() {
    int t[256];
    string s;
    int i;
    cin >> s;
    for (i = 0; i < 256; i++) 
        t[i] = 0;
    for (i = 0; i < s.length(); i++)
        t[s[i]]++;
    for (i = 0; i < s.length(); i++)
        if (t[s[i]] == 1) {
            cout << s[i] << endl;
            return 0;
        }
    cout << "no" << endl;
    return 0;
}

输入xyzxyw,输出结果是

答案

z

这个程序首先统计输入中每个字符的出现次数,存放在字符对应的 ASCII 码下标的数组中;接下来按照字符串输入的字符顺序查找,当找到一个出现次数为 1 的字符时,输出该字符,并直接退出程序。

T24

#include <iostream>
using namespace std;
int g(int m, int n, int x) {
    int ans = 0;
    int i;
    if (n == 1) return 1;
    for (i = x; i <= m / n; i++)
        ans += g(m - i, n - 1, i);
    return ans;
}
int main() {
    int t, m, n;
    cin >> m >> n;
    cout << g(m, n, 0) << endl;
}

输入7 3,输出结果是

答案

8

g(7,3,0)=g(7,2,0)+g(6,2,1)+g(5,2,2)
分别递归计算
g(7,2,0)=g(7,1,0)+g(6,1,1)+g(5,1,2)+g(4,1,3)=1+1+1+1=4
g(6,2,1)=g(5,1,1)+g(4,1,2)+g(3,1,3)=1+1+1=3
g(5,2,2)=g(3,1,2)=1

T25

#include <iostream>
#include <string>
using namespace std;
int main() {
    string ch;
    int a[200];
    int b[200];
    int n, i, t, res;
    cin >> ch;
    n = ch.length();
    for (i = 0; i < 200; i++) 
        b[i] = 0;
    for (i = 1; i <= n; i++) {
        a[i] = ch[i - 1] - '0';
        b[i] = b[i - 1] + a[i];
    }
    res = b[n];
    t = 0;
    for (i = n; i > 0; i--) {
        if (a[i] == 0) 
            t++;
        if (b[i - 1] + t < res)
            res = b[i - 1] + t;
    }
    cout << res << endl;
    return 0;
}

输入1001101011001101101011110001,输出结果是

答案

11

将原串切成两部分,b[i - 1] + t计算的是左段的 1 的个数加上右段的 0 的个数,res维护的是这些值中的最小值

当左段是100,右段是1101011001101101011110001时,此时答案取到 11

T26

#include <iostream>
using namespace std;
int main() {
    int n, m;
    cin >> n >> m;
    int x = 1;
    int y = 1;
    int dx = 1;
    int dy = 1;
    int cnt = 0;
    while (cnt != 2) {
        cnt = 0;
        x = x + dx;
        y = y + dy;
        if (x == 1 || x == n) {
            ++cnt;
            dx = -dx;
        }
        if (y == 1 || y == m) {
            ++cnt;
            dy = -dy;
        }
    }
    cout << x << " " << y << endl;
    return 0;
}

(1)输入4 3时,输出结果是
(2)输入2017 1014时,输出结果是
(3)输入987 321时,输出结果是

答案

(1)1 3
(2)2017 1
(3)1 321

image

x 和 y 方向分开看,来回震荡。求出输入的两个边的最小公倍数 lcm(n-1,m-1),然后用最小公倍数分别除以两个输入的数,如果结果是奇数,则输出的是输入的这个数本身,如果结果是偶数,则输出的是 1

image

第二问:X 方向边长 2016,Y 方向边长 1013
2016=2×2×2×2×2×3×3×7,1013 是质数
X 方向震荡奇数次,Y 方向震荡偶数次
结果:2017 1

第三问:X 方向边长 986=2×17×29,Y 方向边长 320=2×2×2×2×2×2×5
X 方向震荡偶数次,Y 方向震荡奇数次
结果:1 321

T27

(快速幂)请完善下面的程序,该程序使用分治法求 \(x^p \mod m\) 的值。
输入:三个不超过 10000 的正整数 x,p,m
输出:\(x^p \mod m\) 的值
提示:若 p 为偶数,\(x^p=(x^2)^{p/2}\);若 p 为奇数,\(x^p=x*(x^2)^{(p-1)/2}\)

#include <iostream>
using namespace std;
int x, p, m, i, result;
int main() {
    cin >> x >> p >> m;
    result = _____(1)_____;
    while (_____(2)_____) {
        if (p % 2 == 1)
            result = _____(3)_____;
        p /= 2;
        x = _____(4)_____;
    }
    cout << _____(5)_____ << endl;
    return 0;
}
答案

(1)1
(2)p > 0
(3)result * x % m
(4)x * x % m
(5)result

快速幂和取余运算

快速幂、快速幂取模的分析与代码实现

T28

(切割绳子)有 n 条绳子,每条绳子的长度已知且均为正整数。绳子可以以任意正整数长度切割,但不可以连接。现在要从这些绳子种切割出 m 条长度相同的绳段,求绳段的最大长度是多少。
输入:第一行是一个不超过 100 的正整数 n,第二行是 n 个不超过 \(10^6\) 的正整数,表示每条绳子的长度,第三行是一个不超过 \(10^8\) 的正整数 m
输出:绳段的最大长度,若无法切割,输出Failed

#include <iostream>
using namespace std;
int n, m, i, lbound, ubound, mid, count;
int len[100]; // 绳子长度
int main() {
    cin >> n;
    count = 0;
    for (i = 0; i < n; i++) {
        cin >> len[i];
        _____(1)_____;
    }
    cin >> m;
    if (_____(2)_____) {
        cout << "Failed" << endl;
        return 0;
    }
    lbound = 1;
    ubound = 1000000;
    while (_____(3)_____) {
        mid = _____(4)_____;
        count = 0;
        for (i = 0; i < n; i++) 
            _____(5)_____;
        if (count < m) 
            ubound = mid - 1;
        else
            lbound = mid;
    }
    cout << lbound << endl;
    return 0;
}
答案

(1)count += len[i]
(2)count < m
(3)lbound < ubound
(4)(lbound + ubound + 1) / 2
(5)count += len[i] / mid