CSP真题系列(4)-NOIP2017普及组/提高组初赛试题及答案

摘要

CSP非专业级别的能力认证正在报名中。今天整理出NOIP2017初赛试题供大家参考。

NOIP2017初赛提高组真题及答案

一、单项选择题(共 15 题,每题 1.5 分,共计 22.5 分;每题有且仅有一个正确选项)

1. 从( )年开始,NOIP 竞赛将不再支持 Pascal 语言。

A. 2020  B. 2021  C. 2022  D. 2023

2.在 8 位二进制补码中,10101011 表示的数是十进制下的( )。

A. 43   B. -85   C. -43   D.-84

3.分辨率为 1600x900、16 位色的位图,存储图像信息所需的空间为( )。

A. 2812.5KB   B. 4218.75KB

C. 4320KB   D. 2880KB

4. 2017年10月1日是星期日,1949年10月1日是( )。

A. 星期三   B. 星期日

C. 星期六   D. 星期二

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

A.m–n+1   B. m-n

C. m+n+1   D.n–m+1

6. 若某算法的计算时间表示为递推关系式:

T(N)=2T(N/2)+NlogN

T(1)=1

则该算法的时间复杂度为( )。

A.O(N)   B.O(NlogN)

C.O(N log2N)   D.O(N2)

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

A. abcd*+*  B. abc+*d*

C. a*bc+*d  D. b+c*a*d

8. 由四个不同的点构成的简单无向连通图的个数是( )。

A. 32   B. 35   C. 38   D. 41

9. 将7个名额分给4个不同的班级,允许有的班级没有名额,有( )种不同的分配方案。

A. 60   B. 84   C. 96   D.120

10. 若f[0]=0, f[1]=1, f[n+1]=(f[n]+f[n-1])/2,则随着i的增大,f[i]将接近与( )。

A. 1/2    B. 2/3

D. 1

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

A. n2    B. nlogn   C. 2n    D.2n-1

12. 在n(n>=3)枚硬币中有一枚质量不合格的硬币(质量过轻或质量过重),如果只有一架天平可以用来称重且称重的硬币数没有限制,下面是找出这枚不合格的硬币的算法。请把a-c三行代码补全到算法中。

2. 将A中硬币分成X,Y,Z三个集合,使得|X|=|Y|=k, |Z|=n-2k

3. if W(X)≠W(Y) //W(X), W(Y)分别为X或Y的重量

4. then_______

5. else_______

6. __________

7. if n>2 then goto 1

8. if n=2 then 任取A中1枚硬币与拿走硬币比较,若不等,则它不合格;若相等,则A中剩下的硬币不合格

9. if n=1 then A中硬币不合格

正确的填空顺序是( )。

A. b,c,a   B. c,b,a   C. c,a,b   D.a,b,c

13. 在正实数构成的数字三角形排列形式如图所示,第一行的数为a11;第二行的数从左到右依次为a21,a22;…第n行的数为an1,an2,…,ann。从a11开始,每一行的数aij只有两条边可以分别通向下一行的两个数a(i+1)j和a(i+1)(j+1)。用动态规划算法找出一条从a11向下通到an1,an2,…,ann中某个数的路径,使得该路径上的数之和达到最大。

令C[i,j]是从a11到aij的路径上的数的最大和,并且C[i,0]=C[0,j]=0,则C[i,j]=( )。

A. max{C[i-1,j-1],C[i-1,j]}+aij

B. C[i-1,j-1]+c[i-1,j]

C. max{C[i-1,j-1],C[i-1,j]}+1

D. max{C[i,j-1],C[i-1,j]}+aij

14. 小明要去南美洲旅游,一共乘坐三趟航班才能到达目的地,其中第1个航班准点的概率是0.9,第2个航班准点的概率为0.8,第3个航班准点的概率为0.9。如果存在第i个(i=1,2)航班晚点,第i+1个航班准点,则小明将赶不上第i+1个航班,旅行失败;除了这种情况,其他情况下旅行都能成功。请问小明此次旅行成功的概率是( )。

A. 0.5    B. 0.648   C. 0.72   D.0.74

15. 欢乐喷球:儿童游乐场有个游戏叫“欢乐喷球”,正方形场地中心能不断喷出彩色乒乓球,以场地中心为圆心还有一个圆轨道,轨道上有一列小火车在匀速运动,火车有六节车厢。假设乒乓球等概率落到正方形场地的每个地点,包括火车车厢。小朋友玩这个游戏时,只能坐在同一个火车车厢里,可以在自己的车厢里捡落在该车厢内的所有乒乓球,每个人每次游戏有三分钟时间,则一个小朋友独自玩一次游戏期望可以得到( )个乒乓球。假设乒乓球喷出的速度为2个/秒,每节车厢的面积是整个场地面积的1/20。

A. 60   B. 108   C. 18   D. 20

二、不定项选择题(共5题,每题1.5分,共计7.5分;每题有一个或多个正确选项,多选或少选均不得分)

1. 以下排序算法在最坏情况下时间复杂度最优的有( )。

A. 冒泡排序   B. 快速排序

C. 归并排序    D. 堆排序

2. 对于入栈顺序为 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

3. 下列算法中,( )是稳定的排序算法。

A. 快速排序   B.堆排序

C.希尔排序   D. 插入排序

4. 以下是面向对象的高级语言的是( )。

A. 汇编语言   B. C++   C. Fortan  D. Java

5. 以下和计算机领域密切相关的奖项是( )。

A. 奥斯卡奖  B. 图灵奖  C. 诺贝尔奖  D. 王选奖

三、问题求解(共 2 题,每题 5 分,共计 10 分)

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

2. 如图所示,A到B是连通的。假设删除一条细的边的代价是1,删除一条粗的边的代价是2,要让A、B不连通,最小代价是  4  (2分),最小代价的不同方案数是  9  (3分)。(只要有一条删除的边不同,就是不同的方案)

四、阅读程序写结果(共 4 题,每题 8 分,共计 32 分)

1.

#include<iostream>

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;

}

输入: 8  4

输出: 15

2.

#include<iostream>

using namespacestd;

int main() {

int n, i, j, x, y, nx, ny;

int a[40][40];

for (i = 0; i< 40; i++)

for (j = 0;j< 40; j++)

a[i][j]= 0;

cin >> n;

y = 0; x = n-1;

n = 2*n-1;

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

a[y][x] =i;

ny = (y-1+n)%n;

nx = (x+1)%n;

if ((y == 0 && x == n-1) || a[ny][nx] !=0)

y= y+1;

else {y = ny; x = nx;}

}

for (j = 0; j < n; j++)

cout << a[0][j]<< “”;

cout << endl;

return 0;

}

输入: 3

输出: 17 24 1 8 15

3.

#include<iostream>

using namespacestd;

int n, s,a[100005], t[100005], i;

void mergesort(intl, int r){

if (l == r)

return;

int mid = (l + r) / 2;

int p = l;

int i = l;

int j = mid + 1;

mergesort (l, mid);

mergesort (mid + 1, r);

while (i <= mid && j<= r){

if (a[j] < a[i]){

s += mid – i+1;

t[p] = a[j];

p++;

j++;

}

else {

t[p] = a[i];

p++;

i++;

}

}

while (i <= mid){

t[p] = a[i];

p++;

i++;

}

while (j <= r){

t[p] = a[j];

p++;

j++;

}

for (i = l; i <= r; i++ )

a[i] = t[i];

}

int main() {

cin >> n;

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

cin>> a[i];

mergesort (1, n);

cout << s << endl;

return 0;

}

输入:

6

2 6 3 4 5 1

输出: 8

4.

#include<iostream>

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: 1 3  (2 分)

输入2: 2017 1014

输出2: 2017 1 (3 分)

输入3: 987 321

输出3: 1 321 (3分)

五、完善程序(共 2 题,每题 14 分,共计 28 分)

1.

大整数除法:给定两个正整数p和q,其中p不超过10100,q不超过100000,求p除以q的商和余数。(第一空2分,其余3分)

输入:第一行是p的位数n,第二行是正整数p,第三行是正整数q。

输出:两行,分别是p除以q的商和余数。

#include<iostream>

using namespacestd;

int p[100];

int n, i, q,rest;

char c;

int main(){

cin >> n;

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

cin >> c;

p[i] = c – '0’;

}

cin >> q;

rest = p[0];

i = 1;

while (rest< q && i < n){

rest = rest * 10 + p[i];

i++;

}

if (rest < q)

cout << 0 <<endl;

else {

cout << rest / q;

while (i < n){

rest = rest % q * 10 + p[i];

i++;

cout<< rest / q;

}

cout << endl;

}

cout << rest % q<< endl;

return 0;

}

2.

最长路径:给定一个有向五环图,每条边长度为1,求图中的最长路径长度。(第五空 2 分,其余 3 分)

输入:第一行是结点数n(不超过100)和边数m,接下来m行,每行两个整数a,b,表示从结点a到结点b有一条有向边。结点标号从0到(n-1)。

输出:最长路径长度。

提示:先进行拓扑排序,然后按照拓扑排序计算最长路径。

#include<iostream>

using namespacestd;

int n, m, i, j,a, b, head, tail, ans;

int graph[100][100]; // 用邻接矩阵存储图

int degree[100];     // 记录每个结点的入度

int len[100];       // 记录以各结点为终点的最长路径长度

int queue[100];    // 存放拓扑排序结果

int main() {

cin >> n >> m;

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

for (j = 0;j < n; j++)

graph[i][j]= 0;

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

degree[i] =0;

for (i = 0; i < m; i++){

cin>> a >>b;

graph[a][b]= 1;

degree[b]++;

}

tail = 0;

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

if (degree[i] == 0){

queue[tail]= i;

tail++;

}

head = 0;

while (tail < n-1){

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

if(graph[queue[head]] [i] == 1){

degree[i]--;

if(degree[i] == 0){

queue[tail]= i;

tail++;

}

}

head++;

}

ans = 0;

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

a = queue[i];

len[a] = 1;

for (j = 0;j < n; j++)

if(graph[j][a] == 1 && len[j] + 1 >len[a])

len[a]= len[j] + 1;

if (ans < len[a])

ans= len[a];

}

cout << ans << endl;

return 0;

}

NOIP2017初赛普及组真题及答案

一、单项选择题(共 20 题,每题 1.5 分,共计 30 分;每题有且仅有一个正确选项)

1.在 8 位二进制补码中,10101011 表示的数是十进制下的( )。

A. 43  B. -85  C. -43  D. -84

2.计算机存储数据的基本单位是( )。

A. bit  B. Byte  C. GB  D. KB

3.下列协议中与电子邮件无关的是( )。

A. POP3  B. SMTP  C. WTO  D. IMAP

4.分辨率为 800x600、16 位色的位图,存储图像信息所需的空间为( )。

A.937.5KB  B. 4218.75KB

C.4320KB   D. 2880KB

5.计算机应用的最早领域是( )。

A. 数值计算  B. 人工智能

C. 机器人   D. 过程控制

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

A. C   B. C++   C. Java   D. C#

7.NOI 的中文意思是( )。

A. 中国信息学联赛

B. 全国青少年信息学奥林匹克竞赛

C. 中国青少年信息学奥林匹克竞赛

D. 中国计算机协会

8. 2017年10月1日是星期日,1999年10月1日是( )。

A. 星期三  B. 星期日

C. 星期五  D. 星期二

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

A. 36   B. 48   C. 96   D. 192

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

A.m–n+1    B. m-n

C. m+n+1   D.n–m+1

11. 对于给定的序列{ak},我们把 (i, j) 称为逆序对当且仅当 i < j 且 a> aj。那么

序列1, 7, 2, 3, 5, 4的逆序对数为()个。

A. 4   B. 5   C. 6   D. 7

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

A. abcd*+*    B. abc+*d*

C. a*bc+*d    D. b+c*a*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;

14. 若串 S = “copyright”,其子串的个数是( )。

A. 72   B. 45   C. 46   D. 36

15. 十进制小数 13.375 对应的二进制数是( )。

A.1101.011  B. 1011.011

C.1101.101  D. 1010.01

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

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

A. n2   B. nlogn   C. 2n  D. 2n-1

18. 从()年开始,NOIP 竞赛将不再支持 Pascal 语言。

A. 2020  B. 2021  C. 2022  D. 2023

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

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

20. 以下和计算机领域密切相关的奖项是( )。

A. 奥斯卡奖   B. 图灵奖

C. 诺贝尔奖   D. 普利策奖

二、问题求解(共 2 题,每题 5 分,共计 10 分)

1. 一个人站在坐标(0, 0)处,面朝 x 轴正方向。第一轮,他向前走 1 单位距离,然后右转;第二轮,他向前走 2 单位距离,然后右转;第三轮,他向前走 3 单位距离,然后右转......他一直这么走下去。请问第 2017 轮后,他的坐标是: (1009,1008)。(请在答题纸上用逗号隔开两空答案)

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

三、阅读程序写结果(共 4 题,每题 8 分,共计 32 分)

1.

#include<iostream>

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

2.

#include<iostream>

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

3.

#include<iostream>

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<iostream>

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: 1 3  (3 分)

输入2: 2017 1014

输出2: 2017 1 (5 分)

四、完善程序(共 2 题,每题 14 分,共计 28 分)

1. 快速幂:请完善下面的程序,该程序使用分治法求 xp mod m 的值。(第一空2分,其余3分)

输入:三个不超过 10000 的正整数 x,p,m。

输出:xp mod m的值。

提示:若 p 为偶数,xp=(x2)p/2;若 p 为奇数,xp=x*(x2)(p-1)/2

#include<iostream>

using namespacestd;

int x, p, m, i,result;

int main() {

cin >> x >> p >> m;

result = 1 ;

while (p>0) {

if (p % 2 == 1)

result= result*x%m;

p /= 2;

x= x*x%m ;

}

cout << result<< endl;

return 0;

}

2. 切割绳子:有 n 条绳子,每条绳子的长度已知且均为正整数。绳子可以以任意正整数长度切割,但不可以连接。现在要从这些绳子中切割出 m 条长度相同的绳段,求绳段的最大长度是多少。(第一、二空 2.5 分,其余 3 分)

输入:第一行是一个不超过 100 的正整数 n,第二行是 n 个不超过 10的正整数,表示每条绳子的长度,第三行是一个不超过 10的正整数 m。

输出:绳段的最大长度,若无法切割,输出Failed。

#include<iostream>

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];

count+=len[i] ;

}

cin >> m;

if(count<m ){

cout << 'Failed' <<endl;

return 0;

}

lbound = 1;

ubound = 1000000;

while (lbound<ubound){

mid = (lbound+ubound+1)/2;

count = 0;

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

count+=len[i]/mid ;

if (count < m)

ubound = mid - 1;

else

lbound = mid;

}

cout << lbound << endl;

return 0;

}

(0)

相关推荐