2017年NOIP普及组初赛C++语言试题详解
2019-10-10 12:49
郁孤台下清江水,中间多少行人泪。西北望长安,可怜无数山。青山遮不住,毕竟东流去。江晚正愁余,山深闻鹧鸪。
原创+纯手打,如有说的不对的地方,务必轻喷,如果觉得说的还行,就点个赞吧!
NOIP2017普及组初赛解析。初步评价,整体来说,难度比2016增大了,倒并不是说题目思维难度加大很多,而是直接了当的题目少了一些,有10%左右分值的题目是有坑的,一不小心就错了。2017年无论是提高组还是普及组,数学味道都非常浓,计算机科学的基础学科是数学,所以我们要重视数学学科的学习,尤其是与计算机科学相关的组合数学、概率论、离散数学、数列等知识的学习,在OI中,这些知识与数奥的方向并不完全一致,所以对于普及组打基础的小朋友来说,没学过数奥的也不要方!
话不多说,详解如下:
一、单项选择题(共20题,每题1.5分,共计30分;每题有且仅有一个正确选项)
1.在8位二进制补码中,10101011表示的数是十进制下的( )。 A. 43 B.
-85 C. -43 D. -84 【解析】B 正数的原码与反码、补码相同。
负数的反码为原码取反,最高位符号位不变;负数的补码为原码取反加1,最高位符号位不变。
所以,负数的原码为补码减1取反,最高位为符号位不用变。
10101011减1变成10101010,再取反变成11010101
11010101 = -(64 + 16 + 4 + 1) = -85
点评:第一题就有坑,虽然不能算坑。注意这是补码!所以要先转为原码才做进制转换!
补码转原码,取反加1,得到11010101。符号位是1,表明是负数,利用位权法求得-85。 第一道题就暗藏杀机!够狠! 难度指数:☆☆
2.计算机存储数据的基本单位是( )。 A. bit B. Byte C. GB D. KB
【解析】B 计算机存储数据的基本单位是字节Byte
点评:字节(Byte)是基本单位,比特(bit)是最小单位,注意区分。 难度指数:☆ 3.下列协议中与电子邮件无关的是(
)。 A. POP3 B. SMTP C. WTO D. IMAP 【解析】C
WTO: World Trade Organization,世界贸易组织
点评:算是常识题了。就算对邮件协议不是特别了解,WTO这个单词头上有一个大大的提示:“选我”。 难度指数:☆
4.分辨率为800x600、16位色的位图,存储图像信息所需的空间为( )。 A.937.5KB B.
4218.75KB C.4320KB D. 2880KB 【解析】A
8 bit = 1 B1024 B = 1KB800 * 600 * 16 / (8
* 1024) = 937.5kB 点评:高中生做这道题似乎更得心应手些。公式:像素点数量*每个像素点的颜色深度,800*600*16
bit,再进行单位换算。 难度指数:☆☆ 5.计算机应用的最早领域是( )。 A.数值计算 B.人工智能
C.机器人 D.过程控制 【解析】A
美国最早用于计算弹道和射击路线,即数值分析 点评:送分题 难度指数:☆
6.下列不属于面向对象程序设计语言的是( )。 A. C B.
C++ C. Java D. C#
【解析】A C语言是面向过程的语言
点评:程序设计语言知识,难度不大,算常识题,但是平时不注意积累的同学可能不会。 难度指数:☆ 7.NOI的中文意思是(
)。 A.中国信息学联赛 B.全国青少年信息学奥林匹克竞赛 C.中国青少年信息学奥林匹克竞赛 D.中国计算机协会
【解析】B NOI: National Olypiad in
Infomatics,全国青少年信息学奥林匹克竞赛 点评:广告题第一题。试卷抬头就是答案提示。 难度指数:☆ 8.
2017年10月1日是星期日,1999年10月1日是( )。 A.星期三
B.星期日
C.星期五 D.星期二 【解析】C
非闰年,X年10月1日到X+1年10月1日,经过365天。365 % 7 =
1,在星期上相当于过了一天。 闰年一年366天,366 % 7 =
2,在星期上相当于过了二天。
判断闰年有两个条件:能被400整除;或能被4整除且不能被100整除。
1999年10月1日~2017年10月1日,这18年里有13个非闰年5个闰年(2000,2004,2008,2012,2016),相当于经过13
+ 5 * 2 = 23天,23 % 7 = 2,相当于经过了2天。 星期日 - 2
= 星期五。
点评:小学数奥题吗?平年365天,365%7-1,所以正常来说,现在星期x,一年后就是星期x+1,闰年就是x+2,然后可以反推,找出变化的循环节,甚至生推到1999年也行。
难度指数:☆☆☆ 9.甲、乙、丙三位同学选修课程,从4门课程中,甲选修2门,乙、丙各选修3门,则不同的选修方案共有(
)种。 A. 36 B. 48 C. 96 D. 192 【解析】C
求组合数:
点评:基础的排列组合题。首先判断应用分步原理,然后具体每个选择的时候是一个组合问题, 难度指数:☆☆☆
10.设G是有n个结点、m条边(n ≤m)的连通图,必须删去G的( )条边,才能使得G变成一棵树。
A.m–n+1 B. m-n C. m+n+1 D.n–m+1 【解析】A
树的节点数 = 边数 +
1,比如上图中节点10个,边有9条。题目中,图要变 成 树,只能保留n
- 1条边。m - (n - 1) = m - n + 1
点评:学习生成树的时候,就知道n个顶点的生成树有n-1条边。所以答案就是m-(n-1)。比较直接的一道题。 难度指数:☆☆
11.对于给定的序列{ak},我们把(i, j)称为逆序对当且仅当i <
j且ai> aj。那么序列1, 7, 2, 3, 5, 4的逆序对数为( )个。 A. 4 B. 5 C.
6 D. 7 【解析】B 7 2, 7 3, 7 5, 7 4, 5 4。共五对。
点评:可以算是学习题,理解了逆序对的概念后,不难统计出来。比较科学的方法是遍历,按顺序分别统计以1开头的逆序对数量,以7开头的逆序对数量。
逆序对前几年也考过一次 难度指数:☆☆☆ 12.表达式a * (b + c) * d的后缀形式是( )。 A.
abcd*+* B. abc+*d*C. a*bc+*d D. b+c*a*d 【解析】B
考察利用栈将中缀表达式变为后缀表达式。 本题中的执行顺序为: (1)输出a, (2)“”、“(”依次入栈 (3)输出b
(4)“+”入栈 (5)输出c (6)遇到右括号,将栈顶元素“+”出栈并输出,将栈顶元素“(”出栈但不用输出
(7)遇到“”,因为栈中只有一个元素“”,运算符相等,所以“”出栈并输出,新遇到的“”入栈 (8)输出d (9)将栈中的元素“”输出
所以,输出的顺序,即后缀形式为“abc+d”
点评:经典题,考了很多次了。二叉树遍历衍生题型。
两种方法,一种根据中缀表达式画出表达式树,做后序遍历。一种就是加 括号的方式,然后把每层括号中的运算符移到后面(熟练之后括号也 不用加,直接移),去除括号即可。
难度指数:☆☆☆☆
13.向一个栈顶指针为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
考察栈的数据结构,新元素入栈后,要把栈顶指针指到新元素的位置。
点评:有一定难度,而且容易对题意理解错误。注意hs 只是一个栈顶指针,其并没有 next 指针域。
在栈顶插入,只需要保证s->next能指向当前栈顶元素,然后修改hs的指向,把s作为栈顶元素即可。 难度指数:☆☆☆☆
14.若串S = “copyright”,其子串的个数是( )。 A. 72 B. 45 C. 46 D. 36
【解析】C 长度为9的子串有9-9+1=1个,即S本身。
长度为8的子串有9-8+1=2个,即"copyrigh"和"opyright"。
长度为7的子串有9-7+1=3个,即"copyrig",
“opyrigh"和"pyright” ……
长度为1的子串有9-1+1=9个,即"c", “o”, “p”, “y”, “r”,
“i”, “g”, “h”, “t” 长度为0的子串有1个,即空串""
公式cnt = len * (len + 1) / 2 + 1
点评:一道老题,以前考过“Olympiad”,非常容易漏掉空串的情况。 难度指数:☆☆☆
15.十进制小数13.375对应的二进制数是( )。
A.1101.011 B.
1011.011 C.1101.101
D. 1010.01 【解析】A 整数部分,1101 = 2^3 + 2^2 +
2^0 = 13,排除BD
小数部分,小数十进制转二进制,就是小数部分不断乘以2直到小数完全消失,计算过程中每次取整数部分作为二进制值。
0.375 * 2 = 0.75 ,取整数部分0
0.75 * 2 = 1.5,取整数部分1,其小数部分0.5参与下次计算
0.5 * 2 = 1,取整数部分1
所以小数部分为011
点评:经典的进制转换题,分整数和小数部分计算。手算用拼凑法比较快。 难度指数:☆☆ 16.对于入栈顺序为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
A中,每次进栈一个字母,然后该字母立马出栈B中,先入栈a,弹出a;再入栈bcd,弹出dcb;第三次入栈e,弹出e;最后入栈fg,弹出gfC中,无论怎样入栈,都不会有db的出栈顺序D中,把所有字母进栈,再把所有字母出栈
点评:又是经典的判断出栈序列是否合法的问题。基本的做法就是按照进栈顺序,结合选项模拟,选择出现矛盾的选项。 难度指数:☆☆
17.设A和B是两个长为n的有序数组,现在需要将A和B合并成一个排好序的数组,任何以元素比较作为基本运算的归并算法在最坏情况下至少要做(
)次比较。 A. n2 B.
n*logn C.
2n D. 2n-1 【解析】D 考察归并排序
这题考的是比较次数,而不是时间复杂度或空间复杂度。 先看看最好的情况,设有序数组A[4] = {1, 3, 5, 7},
有序数组B[4] = {8, 10, 12, 14}, 数组C[8]用来存储比较后的结果。 1与8比较,把1放到C中,C[] =
{1} 3与8比较,把3放到C中,C[] = {1, 3} 5与8比较,把5放到C中,C[] = {1, 3, 5}
7与8比较,把7放到C中,C[] = {1, 3, 5, 7} 剩下的不用比较,直接放到C中,C[] = {1, 3, 5, 7,
8, 10, 12, 14} 共比较了4次,即n次 再看看最坏的情况,设有序数组A[4] = {1, 3, 5, 7},
有序数组B[4] = {2, 4, 6, 8}, 数组C[8]用来存储比较后的结果。
1与2比较,把1放到C中,C[] = {1}
2与3比较,把2放到C中,C[] = {1, 2}
3与4比较,把3放到C中,C[] = {1, 2, 3}
4与5比较,把4放到C中,C[] = {1, 2, 3, 4}
5与6比较,把5放到C中,C[] = {1, 2, 3, 4, 5}
6与7比较,把6放到C中,C[] = {1, 2, 3, 4, 5,6}
7与8比较,把7放到C中,C[] = {1, 2, 3, 4, 5, 6, 7}
最后的8不用比较,直接放到C中,C[] = {1, 2, 3, 4, 5, 6, 7,
8} 共比较了7次,即2n - 1次
点评:特殊值法比较快,比如n=1时,要一次比较,代入发现ABD均可,再代入n=2时,比如A是1和3,B是2和4,那么要3次比较,这样只有D答案符合。
难度指数:☆☆☆ 18.从( )年开始,NOIP竞赛竟不再支持Pascal语言。 A. 2020 B.
2021 C. 2022 D. 2023 【解析】C
从2022年开始,不可使用C和Pascal,只能使用C++
点评:又是一道广告题!有点不按基本法出题了。 难度指数:☆
19.一家四口人,至少两个人生日属于同一月份的概率是()(假定每个人生日属于每个月份的概率相同且不同人之间相互独立)。 A.
1/12 B. 1/144 C. 41/96D. 3/4 【解析】C
设P(A)表示至少两个人生日在同一月份的概率,P(A’)表示四个人的生日都不在同一月份的概率,则P(A)
= 1 - P(A’) P(A’) = A(12, 4) / 12 ^ 4 = 12
* 11 * 10 * 9 / (12 * 12 * 12 * 12)= 55 / 96
P(A) = 1 - P(A’) = 41 / 96
点评:最难的一道题,概率题,高考级别? 难度指数:☆☆☆☆☆ 20.以下和计算机领域密切相关的奖项是( )。
A.奥斯卡奖 B.图灵奖 C.诺贝尔奖
D.普利策奖 【解析】B
奥斯卡是电影类的奖项诺贝尔有六种奖项:物理、化学、生物和医疗、文学、经济、和平普利策是新闻类的奖项
点评:送分题 难度指数:☆ 选择题总评:
9、13、19比较难,4虽然不一定学过,但是根据选项可以尝试精测计算,8需要细心。总体而言,对于经过系统培训足够时间的学生来说,难度不算很大。考题也比较常规,除了两道广告题以外。
二、问题求解(共2题,每题5分,共计10分) 1.一个人站在坐标(0,
0)处,面朝x轴正方向。第一轮,他向前走1单位距离,然后右转;第二轮,他向前走2单位距离,然后右转;第三轮,他向前走3单位距离,然后右转......他一直这么走下去。请问第2017轮后,他的坐标是:
_____________________。(请在答题纸上用逗号隔开两空答案) 参考答案:(1009,1008) 【解析】
根据题意描述,可以比较容易的发现坐标变化规律。 x+1 y-2 x-3 y+4 X+5 y-6 x-7 y+8 .... y+2016
x+2017 以4为周期,容易看出x的变化是
1-3+5-7+..+2013-2015+2017=(1-3)+(5-7)+.+(2013-2015)+20172017/4=504,有504个循环节,所以x=-2*504+2017=1009
类似地, y的变化规律是 -2+4-6+..+2016=2*504=1008
2.如图所示,共有13个格子。对任何一个格子进行一次操作,会使得它自己以及与它上下左右相邻的格子中的数字改变(由1变0,或由0变1)。现在要使得所有的格子中的数字都变为0,至少需要__________次操作。
参考答案:3 【解析】
分别把黄、红和绿色部分操作,即可达到目的。此题可能来源于摩尔庄园中的一个游戏
问题求解总评:问题求解比较注重考查观察和思维,数学好的同学会占有优势。 难度指数:☆☆☆
三、阅读程序写结果(共4题,每题8分,共计32分) 1. #include using namespacestd; 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 【解析】
注意到if语句中的return0;输出第一个字符之后直接结束程序了。
程序功能是统计字符串中个字符出现的次数,并且输出第一个只出现一次的字符。
点评:目测又会引发很多惨案,很多人没注意到if语句中的returm0;输出第一个字符之后直接结束程序了 难度指数:☆☆☆ 2.
#include using namespacestd; int g(int m, intn, 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;
return 0; } 输入: 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
最后计算出结果。 点评:一个比较简单的递归程序。细心一些是可以直接计算出来的。 难度指数:☆☆ 3.
#include using namespacestd; 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 点评:代码其实不长,直接模拟,细心些可以做出来。 难度指数:☆☆☆ 4. #include using
namespacestd; 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 输出1:____________。(3分) 输入2: 2017 1014 输出2:____________。(5分)
参考答案: 输出1: 1 3 输出2: 2017 1 【解析】
经过输入1的尝试,可以发现一些规律: x的变化:1 2 3 4 3 2 1 y的变化:1 2 3 2 1 2 3
x和y的数据变化都有各自的周期,当恰好同时满足(x==1or x==)和(y==1or y==m)的时候就输出。 所以输入2可以
x:1 2 3 4..............2017
y:1 2 3 4..1014 1013..1 点评:简单规律题,暴力模拟即可 难度指数:☆
四、完善程序(共2题,每题14分,共计28分) 1.快速幂 请完善下面的程序,该程序使用分治法求xp mod
m的值。(第一空2分,其余3分) 输入:三个不超过10000的正整数x,p,m。 输出:xpmod m的值。
提示:若p为偶数,xp=(x2)p/2;若p为奇数,xp=x*(x2)(p-1)/2。 #include using
namespacestd; int x, p, m, i,result; int main() { cin >> x
>> p >> m; result = ____①__ ; while (___②___) { if
(p % 2 == 1) result= ___③_____; p /= 2; x=____④_____ ; } cout
<< _______⑤______<< endl; return 0; } 参考答案: ① ② ③ ④ ⑤ 1
p>0或p!=0 result*x%m x*x%m result
点评:学习过的很快就能全部填出来,没学过的只能现学了,总体来说,都是比较好猜的,至少2个空是可以的。 难度指数:☆☆☆☆ 2.切割绳子
有 n 条绳子,每条绳子的长度已知且均为正整数。绳子可以以任意正整数长度切割,但不可以连接。现在要从这些绳子中切割出 m
条长度相同的绳段,求绳段的最大长度是多少。(第一、二空 2.5 分,其余 3 分)
输入:第一行是一个不超过 100 的正整数 n,第二行是 n 个不超过 106
的正整数,表示每条绳子的长度,第三行是一个不超过 108 的正整数 m。 输出:绳段的最大长度,若无法切割,输出Failed。
#include using namespacestd; 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];
____①_____; } cin >> m; if(____②____){ cout << "Failed"
<<endl;< p=""> return 0; } lbound = 1; ubound =
1000000; while (____③____){ mid =____④____; count = 0; for (i = 0;
i < n; i++) ____⑤____; if (count < m) ubound = mid - 1; else
lbound = mid; } cout << lbound << endl; return 0; }
参考答案: ① count =count+len[i]或count +=len[i] ② countcount ③
lboundlbound ④ (1bound+ubound+1)/2或(1bound+ubound)/2+1 ⑤
count=count+1en[i]/mid或count+=len[i]/mid
点评:充分理解题意后还是比较好填空的,3、4空比较好填,其次是1、2空。 难度指数:☆☆☆ 完善程序总评:
经典算法还是喜欢考,二分法尤其喜欢考,提高喜欢考,普及也喜欢考。要加强
NOIP必备算法的学习了。
以上是对2017NOIP初赛题目的解析,希望对大家复盘有所帮助,毕竟很快就要考试了!希望各位都能有一个好成绩!
--end--
声明:本文章由网友投稿作为教育分享用途,如有侵权原作者可通过邮件及时和我们联系删除:freemanzk@qq.com