NOIP-2015-J1-真题解析

一、选择题

1、D,基础题,考察存储单位, 1 M B = 1024 K B = 1024 ∗ 1024 B 1MB=1024KB=1024*1024B 1MB=1024KB=10241024B
2、C,基础题,考察硬件常识,市场上常见的CPU型号
3、C,基础题,考察操作系统的基本概念,操作系统的主要作用是控制和管理系统资源
4、A,基础题,考察计算机基本工作原理,底层数据存储格式
5、A,基础题,考察计算机硬件系统,A正确,B错误,内存储器断电后信息丢失,C错误,显示屏屏幕尺寸和分辨率没有关系,D错误,除了wifi,还有有线等其他方式连接到internet
6、D,基础题,二进制加法
7、A,基础题,进制转换,二进制转16进制,小数部分要乘以8即可
8、B,基础题,考察操作系统基础知识,中断的概念
9、B,基础题,考察计算机安全,计算机病毒相关常识
10、A,基础题,考察计算机网络应用层常用协议,FTP是文件传输协议
11、D,基础题,考察常用应用软件常识
12、B,数据结构题,考察图生成树的边数和顶点数的关系,边数等于顶点数减1
13、A,数据结构题,考察链表基本概念,链表不可以随机访问任何一个元素,必须从头遍历
14、D,数据结构题,考察信息表的链式存储结构特点,当采用链表存储时,链表的各个结点存储单元是动态分配的,其地址连续不连续均可
15、B,数据结构题,考察栈的出栈序列,根据题意直接模拟可得B
16、D,数据结构题,考察二叉树遍历,要想前序遍历和中序遍历相同,则二叉树的每个非叶子结点不能有左子树
17、B,数据结构题,考察二叉树高度计算,高度为h完全二叉树结点数最多 2 h − 1 2^h-1 2h1,最少为 2 h − 1 + 1 2^{h-1}+1 2h1+1,61刚好介于33,63之间,故h=6
18、A,基础题,考察多媒体常识,常见视频文件格式,BCD均是,TXT是文本文件格式
19、D,算法题,考察时间复杂度估算,根据递推式可以得到T=1+2+…+n,所以是O(n^2)
20、A,竞赛常识题,鼠标,以及计算机都是由考试单位统一提供,不得自带,BCD均是要自带的

二、问题求解

1、数学题,考察组合数学,错位排列,需要记住错位排列递推公式,f(4)=9
f ( n ) = ( n − 1 ) ∗ ( f ( n − 1 ) + f ( n − 2 ) ) , f ( 1 ) = 0 , f ( 2 ) = 1 f(n)=(n-1)*(f(n-1)+f(n-2)),f(1)=0,f(2)=1 f(n)=(n1)(f(n1)+f(n2))f(1)=0,f(2)=1
2、数据结构题,考察二叉树结点数,常考题型,叶子结点最多的时候是完全二叉树的时候,2015个结点的完全二叉树,总共有11层,11层的满二叉树有2047个结点,底层有2^10=1024个叶子结点,将底层剪掉32个结点,底层剩余叶子结点数为1024-32,然后倒数第二层有16个结点变成了叶子结点,所以总共有1024-32+16=1008个叶子结点。

三、阅读程序

1、

#include <iostream> 
using namespace std;
int main() 
{
    int a, b, c; a = 1;
    b = 2;
    c = 3;
    if(a > b)
        if(a > c)
            cout << a << ' ';
        else
        cout << b << ' '; 
    cout << c << endl;
    return 0;
}

简单编程题,考察if-else语句,输出为3

2、

#include <iostream>
using namespace std;
struct point
{
    int x;
    int y;
};

int main()
{
    int a, b, c;
    struct EX
    {
        int a;
        int b;
        point c;
    } e;

    e.a    = 1;
    e.b    = 2;
    e.c.x= e.a + e.b;
    e.c.y= e.a * e.b;
    cout << e.c.x << ',' << e.c.y << endl;
    return(0);
}

编程题,考察结构体应用,输出为3,2

3、

#include <iostream>
#include <string> 
using namespace std;

int main()
{
    string str;
    int i;
    int count; count = 0;
    getline( cin, str );
    for ( i = 0; i < str.length(); i++ )
        if ( str[i] >= 'a' && str[i] <= 'z' )
            count++;
    cout << "It has " << count << " lowercases" << endl; return(0);
}

输入:NOI2016 will be held in Mian Yang.
编程题,考察字符串处理,代码里是遍历输入的字符串,判断每个字符是否是小写字母,若是则计数加1,最后输出计数值,数一下可得18,输出为:It has 18 lowercases

4、

#include <iostream>
#include <string>
using namespace std;

void fun( char *a, char *b )
{
  a = b;
  (*a)++;
}


int main()
{
  char c1, c2, *p1, *p2;
  c1 = 'A';
  c2 = 'a';
  p1 = &c1;
  p2 = &c2;
  fun( p1, p2 );
  cout << c1 << c2 << endl;
  return(0);
}

编程题,考察指针和函数参数传递。p1,p2分别是指向c1,c2的指针,作为实参调用函数fun,实参的值传递个fun的形参a,b,a,b也分别指向c1,c2,然后b赋值给a,故a指向了c2,然后通过指针修改c2的值,使其自增1,所以最后c1不变,c2的值增1,由字符a变成b,输出为:Ab

四、完善程序

1、(打印日历) 输入月份 m(1≤m≤12),按一定格式打印 2015 年第 m 月的月历。(第三、四空 2.5 分, 其余 3 分)
例如,2015 年 1 月的月历打印效果如下(第一列为周日):

#include <iostream>
#include <string>
using namespace std;
const int dayNum[] = {-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int m, offset, i;
int main()
{
    cin >> m;
    cout << "S\tM\tT\tW\tT\tF\tS" << endl; /* '\t'为 TAB 制表符 */;
    for (i = 1; i < m; i++)
        offset =;
    for (i = 0; i < offset; i++)
        cout << '\t';
    for (i = 1; i <=; i++)
    {
        cout <<;
        if (i == dayNum[m] ||== 0)
            cout << endl;
        else
            cout << '\t';
    }
    return (0);
}

编程题,考察循环语句应用,输出2015年第m个月的月历,代码里枚举了12个月每个月的天数,然后题干给出第1个月的月历,相当于给出了初始条件,2015年的第1天是星期4,在月历的第一行前面要先空出4个位置,offset表示偏移,初始为4,①offset=4,然后计算前m-1个月的总天数加起来的偏移,每7天一行,模7即可,②(offset+dayNum[i])%7,最后得到的即是第m月的第一天的偏移offset,输出offset个制表符\t,然后开始依次输出第m月的每一天,每输出一个,需要判断当前是否到达月末或刚好模7为0,若是则需要换行,否则输出\t,④i,⑤(offset+i)%7

2、(中位数 median) 给定 n(n 为奇数且小于 1000)个整数,整数的范围在 0~m(0<m<2^31)之间,请使用二分法求这 n 个整数的中位数。所谓中位数,是指将这 n 个数排序之后,排在正中间的数。(第五空 2分,其余 3 分)

#include <iostream>
using namespace std;

const int MAXN = 1000;
int n, i, lbound, rbound, mid, m, count;
int x[MAXN];

int main()
{
    cin >> n >> m;
    for (i = 0; i < n; i++)
        cin >> x[i];
    lbound = 0;
    rbound = m;
    while ()
    {
        mid = (lbound + rbound) / 2;;
        for (i = 0; i < n; i++)
            if ();
        if (count > n / 2)
            lbound = mid + 1;
        else;
        cout << mid << " " << lbound << " " << rbound << " " << count << endl;
    }
    cout << rbound << endl;
    return (0);
}

算法题,考察二分法的应用,注意题目给出的n是奇数,所以中位数刚好是按大小顺序排在正中间的那个数。题目给出的代码没有直接排序然后取中间的数,而是通过计数搭配二分查找来确定中位数,思路也非常明确。假设n个数排好序了,那中位数mid是位于正中间的,大于mid的数的个数最多有n/2个,最少0个,比如n=5,m=5时的两种情况:
在这里插入图片描述

对序列取值范围0-m内每个数i,从左至右依次统计序列中大于其i的个数count,这样的count构成的必然是一个非递增序列,序列中第一个count小于等于n/2的i就是中位数。
显然就是二分边界查找问题,是降序序列的左边界查找,所以①lbound<rbound,边界查找循环条件,②count=0,初始化每一次循环的计数,③x[i]>mid,统计计数,④count++,计数累加,如果大于当前mid的数超过n/2,这要在右边更大区间里查找,否则mid可能是结果,真正的答案也可能在mid左侧,所以继续往左边缩小范围,往左继续查找,⑤rbound=mid
循环退出的时候lbound必然与rbound相等,答案即可以是lbound也可以是rbound。

总评

本题试题侧重基础知识考察,特别是选择题基础知识比重较大,阅读程序题也比较基础简单,比如循环语句,字符串处理,完善程序中位数采用二分查找算法,需要牢记二分查找的几种查找的模板写法,灵活应用。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

严老师编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值