NOIP2013-普及组初赛C语言解析
第十九届全国青少年信息学奥林匹克联赛初赛
一、单项选择题(共 20 题,每题 1.5 分,共计 30 分。每题有且仅有一个正确选项)
1. 一个 32 位整型变量占用(A )个字节。
A. 4 B. 8 C. 32 D. 128
参考:一个int变量占4个字节,对于16字机,short int 占2个字节,在大多数的32位机中,short int 占4个字节。但总的来说,short int 至少16位,也就是2个字节,long int或long ,在内存中占4个字节。故选A
/============================================================================================/
2. 二进制数 11.01 在十进制下是( A) 。
A. 3.25 B. 4.125 C. 6.25 D. 11.125
参考:关于小数的二进制转十进制,先把整数按照一般方法转成二进制,小数部分,
举例:
所以本题中的整数二进制转换过程为:1*2º+1*2¹(从后往前乘)=3,
小数部分转换过程为:
0*2º+0*2^-1+1*2^-2=0.25
所以(11.01)₂=(3+0.25=3.25)₁₀,故选A
/============================================================================================/
3. 下面的故事与( B)算法有着异曲同工之妙。
从前有座山,山里有座庙,庙里有个老和尚在给小和尚讲故事:‚从前有座山,山
里有座庙,庙里有个老和尚在给小和尚讲故事:‘从前有座山,山里有座庙,庙里有个
老和尚给小和尚讲故事....’‛
A. 枚举 B. 递归 C. 贪心 D. 分治
参考:这题一个套一个,无限循环,很明显是递归,故选B
/============================================================================================/
4. 逻辑表达式( C)的值与变量 A 的真假无关。
A. (A ˅ B) ˄ ¬A B. (A ˅ B) ˄ ¬B
C. (A ˄ B) ˅ (¬A ˄ B) D. (A ˅ B) ˄ ¬A ˄ B
参考:其中"∨" 表示"或" (逻辑加法),"∧" 表示"与". (逻辑乘法),"┐"表示"非". (逻辑否定),代入几组数据,可以求得“(A ˄ B) ˅ (¬A ˄ B)”的真假与A无关,故选C
/============================================================================================/
5. 将( 2, 6, 10, 17) 分别存储到某个地址区间为 0~10 的哈希表中, 如果哈希函数 h(x) =
(D ),将不会产生冲突,其中 a mod b 表示 a 除以 b 的余数。
A. x mod 11 B. x2 mod 11
C. 2x mod 11 D. ⌊√ ⌋ mod 11,其中⌊√ ⌋表示√ 下取整
参考:所谓哈希表,就是建立一个数组模样的,通过对元素的某种计算出下表的位置放入,更加快捷(它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度),当0~10之内的数,mod 11向下取整就不会发生重复,故选D
/============================================================================================/
6. 在十六进制表示法中,字母 A 相当于十进制中的(B ) 。
A. 9 B. 10 C. 15 D. 16
参考:十六进制表:0,1,2,3,4,5,6,7,8,9,A(10),B(11),C(12),D(13),E(14),F(15),故选B
/============================================================================================/
7. 下图中所使用的数据结构是( B) 。
A. 哈希表 B. 栈 C. 队列 D. 二叉树
参考:只有一个出口,要想把底下的东西拿出来,只能把上面的东西先拿走,所以是栈,故选B
/============================================================================================/
8. 在 Windows 资源管理器中, 用鼠标右键单击一个文件时,会出现一个名为“复制”的
操作选项,它的意思是(C )。
A. 用剪切板中的文件替换该文件
B. 在该文件所在文件夹中,将该文件克隆一份
C. 将该文件复制到剪切板,并保留原文件
D. 将该文件复制到剪切板,并删除原文件
参考:Window系统中,“复制”是把文件放入剪切板,保留文件,点击“粘贴”时,从剪切板内发送到目标文件下,故选C
/============================================================================================/
9. 已知一棵二叉树有 10 个节点,则其中至多有(A )个节点有 2 个子节点。
A. 4 B. 5 C. 6 D. 7
参考:2³=8<x<2⁴=16,故选A
/============================================================================================/
10. 在一个无向图中,如果任意两点之间都存在路径相连,则称其为连通图。下图是一个有
4 个顶点、 6 条边的连通图。若要使它不再是连通图, 至少要删去其中的(C )条边。
A. 1 B. 2 C. 3 D. 4
参考:这是一个无向图,每个点都能到达其他任意一个点,则要使它不是连通图,则需要把一个点孤立在外,就需要删除3条边即可,故选C
/============================================================================================/
11. 二叉树的(A ) 第一个访问的节点是根节点。
A. 先序遍历 B. 中序遍历 C. 后序遍历 D. 以上都是
参考:先序遍历:先访问根节点,再到左右节点
中序遍历:先访问左节点,再访问根节点,最后访问右节点
后序遍历:先访问左节点,再到右节点,最后根节点
/============================================================================================/
12. 以 A0作为起点,对下面的无向图进行深度优先遍历时,遍历顺序不可能是( ) 。
A. A0, A1, A2, A3 B. A0, A1, A3, A2 C. A0, A2, A1, A3 D. A0, A3, A1, A2
参考:既然是深度优先遍历,就要一直访问到一个节点最后一层,则A是错的,A为广搜,故选A
/============================================================================================/
13. IPv4 协议使用 32 位地址,随着其不断被分配,地址资源日趋枯竭。因此,它正逐渐被
使用( D)位地址的 IPv6 协议所取代。
A. 40 B. 48 C. 64 D. 128
参考:IPv4地址就是四位IP地址,如:192.168.0.1,但随着社会的发展,IPv4地址很快被用尽,现在已经使用了128位的IPv6地址,如:00-01-00-01-1D-8F-D3-2A-90-E6-BA-E2-42-E3,故选D
/============================================================================================/
14. (A )的平均时间复杂度为 O(n log n),其中 n 是待排序的元素个数。
A. 快速排序 B. 插入排序 C. 冒泡排序 D. 基数排序
参考:快速排序最好情况是n log n,最坏是n²,所以平均复杂度是n log n
/============================================================================================/
15. 下面是根据欧几里得算法编写的函数,它所计算的是 a 和 b 的(C )。
int euclid(int a, int b)
{
if (b == 0)
return a;
else
return euclid(b, a % b);
}
A. 最大公共质因子 B. 最小公共质因子
C. 最大公约数 D. 最小公倍数
参考:从代码可以看出,是运用了函数递归,辗转相除法求最大公约数,故选C
/============================================================================================/
16. 通常在搜索引擎中,对某个关键词加上双引号表示(C ) 。
A. 排除关键词,不显示任何包含该关键词的结果
B. 将关键词分解,在搜索结果中必须包含其中的一部分
C. 精确搜索,只显示包含整个关键词的结果
D. 站内搜索,只显示关键词所指向网站的内容
参考:这题是常识题,例如在百度中,在内容前后加上双引号表示的是精确搜索(词条不会被分开),故选C
/============================================================================================/
17. 中国的国家顶级域名是( A)。
A. .cn B. .ch C. .chn D. .china
参考:这题是常识题,A是中国国家顶级域名,B是瑞士的域名,C选项chn虽然是中国的意思,但没有这个域名,D选项更不可能,故选A
/============================================================================================/
18. 把 64 位非零浮点数强制转换成 32 位浮点数后, 不可能( D)。
A. 大于原数 B. 小于原数
C. 等于原数 D. 与原数符号相反
参考:把一个 64 位非零浮点数强制转换成 32 位浮点数后,符号不可能相反,只是数可能变大变小或者不变,故选D
/============================================================================================/
19. 下列程序中,正确计算 1, 2, …, 100 这 100 个自然数之和 sum (初始值为 0)的是(A )
参考:i初值为1,sum每次+i,且while循环(i≤100成立)加上,A正确,B只有当i>100时成立,错误,C还要考虑等于100的情况,错误,D的错误和B一样,故选A
/============================================================================================/
20. CCF NOIP 复赛全国统一评测时使用的系统软件是(B )。
A. NOI Windows B. NOI Linux C. NOI Mac OS D. NOI DOS
参考:目前NOIP复赛用的是虚拟机评测,用的是Linux系统,故选B
/============================================================================================/
二、问题求解(共 2 题,每题 5 分,共计 10 分;每题全部答对得 5 分, 没有部分分)
1.7个同学围坐一圈,要选两个不相邻的人作为代表,有 14 种不同的选法
参考:可以把这七个人想象成为一个七边形,问题变为了“求七边形有多少条对角线”,这样就可以运用公式求出共有x个选法(x条对角线)=n(n-3)/2=14
/===========================================================================================/
2.某程序自称使用了一种防窃听的方式验证用户密码。密码是n个数S₁、S₂…Sn,均为0或1.该系统随机生成n个数,a₁,a₂…an,均为0或1,请用户回答(S₁a₂+S₁a₂+…Snan)除以二的余数。如果多次回答总是正确,即认为掌握密码。该系统认为,及时回答的过程被泄露,也无助于破解密码——因为用户并没有直接发送密码。
然而,事与愿违。例如,当n=4时,有人窃听了以下五次回答:
就破解出了密码S₁= 0 S₂= 1 S₃= 1 S₄= 1
参考:根据用户的回答,代入a1、a2、a3、a4,可以倒推出有关S1,S2,S3,S4的关系式:
(S1+S2)%2=1① (S1+S2+S3)%2=0④
(S3+S4)%2=0② (S1)%2=0⑤
(S2+S3)%2=0③
根据上面五个式子中的⑤式,可以推出S1=0,将S1代入①式,得出S2=1,将S2代入③式,得出S3=1,将S3代入②式,得出S4=1;
三、阅读程序写结果(共 4 题,每题 8 分,共计 32 分)
1.
1 #include <stdio.h>
2 int main()
3 {
4 int a,b;
5 scanf("%d%d",&a,&b);
6 printf("%d+%d=%d\n",a,b,a+b);
7 return 0;
8 }
输入:3 5
输出: 3+5=8
参考:这题简单,输入两个数a,b,写出表达式"a+b=c",所以是3+5=8
/============================================================================================/
2.
1 #include <stdio.h>
2 int main()
3 {
4 int a,b,u,i,num;
5 scanf("%d%d%d",&a,&b,&u);
6 num=0;
7 for(i=a;i<=b;i++)
8 {
9 if((i%u)==0)
10 num++;
11 }
12 printf("%d\n",num);
13 return 0;
14 }
输入:1 100 15
输出: 6
参考:这题简单,从代码中不难看出,从a-b这个范围内寻找u的倍数有多少个,所以是6
/============================================================================================/
3.
1 #include <stdio.h>
2 const int SIZE=100;
3 int main()
4 {
5 int n,f,i,left,right,middle,a[SIZE];
6 scanf("%d%d",&n,&f);//输入两个数n和f
7 for(i=1;i<=n;i++)//循环n次
8 scanf("%d",&a[i]);//每次输入一个数存入数组a
9 left=1;//left标记为第一
10 right=n;//right标记为最后
11 do
12 {
13 middle=(left+right)/2;//middle赋值为左右中值
14 if(f<=a[middle]){//如果f小于a数组中间那个数
15 right=middle;//right标记为中值
16 }
17 else{
18 left=middle+1;//否则left标记为中值+1
19 }
20 }while(left<right);//循环直到left≥right时结束
21 printf("%d\n",right);//输出f在数组a中的位置
22 return 0;
23 }
输入:12 17
2 4 6 9 11 15 17 18 19 20 21 25
输出: 7
参考:从代码可以看出,输入两个数n和f,循环n次,每次输入一个数存入数组a。定义两个数left、right分别标记为第一和最后。在下面一个while循环直到left≥right时结束。这个循环中,middle赋值为左右中值,如果f小于a数组中间那个数right标记为中值,反之left标记为中值+1,重复过程,从这个过程可以看出,左和右每次都折半,寻找f(二分查找f在数组a中的位置),最后输出f的位置。所以17在"2 4 6 9 11 15 17 18 19 20 21 25"中的位置是第7个。
二分查找这种算法是比较高效的,在编程中经常要用到。
/============================================================================================/
4.
1 #include <stdio.h>
2 const int SIZE=100;//宏定义SIZE代表100
3 int main()
4 {
5 int height[SIZE],num[SIZE],n,ans;//height数组表示高度,num表示升序列长度
6 int i,j;
7 scanf("%d",&n);//输入共有n个数
8 for(i=0;i<n;i++)
9 {
10 scanf("%d",&height[i]);//每次输入一个数到数组height中
11 num[i]=1;//长度标记为1
12 for(j=0;j<i;j++)//从0~i范围内寻找能和i构成最长升序序列的数
13 {
14 if((height[j]<height[i])&&(num[j]>=num[i]))//如果i比前面的一个数大,且num长度最大(0~i能和i构成目前最长升序子序列)
15 num[i]=num[j]+1;//则升序子序列长度+1
16 }
17 }
18 ans=0;//ans清零
19 for(i=0;i<n;i++)//寻找num数组中的最大升序列长度ans,输出
20 {
21 if(num[i]>ans) ans=num[i];//发现有一个更长的长度,ans标记为当前
22 }
23 printf("%d\n",ans);
24 return 0;
25 }
输入:6
2 5 3 11 12 4
输出: 4
参考:这题较为复杂,题目中要求输入一组高度,每次从0~i寻找之前的数是否小于当前i并且长度num要大于i当前的num值,满足条件,加上去。如果不明白意思的话,可以模拟一下过程即可
所以这个代码的作用是:求一个数列中最大升序子序列长度,所以题目中的"2 5 3 11 12 4"中最大升序子序列是“2 3 11 12”,长度是4。
/============================================================================================/
四、完善程序( 共 2 题, 每题 14 分, 共计 28 分)
1.( 序列重排) 全局数组变量 a 定义如下:
它记录着一个长度为 n 的序列 a[1], a[2], …, a[n]。
现在需要一个函数, 以整数 p (1 ≤ p
≤ n)为参数,实现如下功能: 将序列 a 的前 p
个数与后 n – p 个数对调, 且不改变这 p 个数(或 n – p 个数)之间的相对位置。例如,
长度为 5 的序列 1,
2, 3, 4, 5,当 p = 2 时重排结果为 3, 4, 5, 1, 2。
有一种朴素的算法可以实现这一需求, 其时间复杂度为 O(n)、空间复杂度为 O(n):
参考:这题呢,较为简单,我们先开第一段代码。这段代码较为朴素,第一个for循环是把p后面的数存入b数组,