NOIP-2014-J1-真题解析

一、选择题

1、B,基础题,考察常用编程语言类型,汇编语言是介于机器语言和高级语言之间的,C++是面向对象的高级语言,Fortran和Basic是面向过程的高级语言
2、D,基础题,考察存储单位换算, 1 T B = 2 10 G B = 2 20 M B = 2 30 K B = 2 40 B 1TB=2^{10}GB=2^{20}MB=2^{30}KB=2^{40}B 1TB=210GB=220MB=230KB=240B
3、D,基础题,考察二进制的算术运算
4、D,基础题,考察计算机外部设备,ABC均是输入设备,D打印机是输出设备
5、C,基础题,考察操作系统基本概念,对操作系统功能描述最为完整的是C,控制和管理计算机系统的各种硬件和软件资源的使用
6、B,基础题,考察计算机硬件系统,总线的基本功能,总线连接CPU,存储器,I/O设备,是这些设备之间互联互通,交换数据的通路
7、A,基础题,考察计算机硬件系统,常见存储器,RAM常见于内存储器,断电后数据消失,ROM是只读存储器,常见于BIOS芯片,通常用于存储一段固化程序,是永久存储,断电后数据不会消失,硬盘和光盘都是可永久存储数据的,断电后不会丢失数据
8、A,基础题,考察计算机网络,常见网络协议,SMTP是邮件传输协议,属于应用层协议,UDP是传输层协议,P2P,FTP都是应用层协议
9、B,基础题,ACD均是图像格式,TXT是文本文件格式
10、B,数据结构题,考察链表的基本特征,链表不支持随机访问任一元素
11、D,基础题,考察二进制,八位二进制能表示的数的范围是0-255,所以只有D,199符合
12、C,基础题,考察计算机网络,IP地址基本概念,32位IP地址,由4块组成,每块由8位二进制表示,数据范围是0-255,C中出现了256,所以错误
13、C,编程题,考察除运算符,对于该运算符,若除数与被除数均为整数,则结果也是整数,若除不尽,则小数部分被截掉,只留整数部分,所以代码中1/n,因为n都是大于1,所以1/n总数返回0,无法得到题目想要的结果,是错误的写法。
14、C,编程题,考察强制类型转换,要保留小数点后两位,并四舍五入的话,必然需要做强制类型转换,A将x的值扩大了100倍,错误,B和D修改了x的值,但都没有保留2位小数
15、B,编程题,考察do-while循环语句,s初值为0,输出时s为2,则do-while循环执行了2次,a初值为1,循环两次后,减掉4,得-3,此刻要退出循环,所以n=-3,输入的n的值为-3
16、A,数据结构题,考察满二叉树的结点计算,n层的满二叉树结点数为2^n-1,n=5时,结过是31
17、C,数据结构题,考察有向图的度的概念,每个顶点的度等于其入度和出度之和
18、B,算法题,考察折半查找,对于n个元素序列上的折半查找,最大比较次数为:
⌊ l o g 2 n ⌋ + 1 \lfloor log_2^n\rfloor +1 log2n+1
将n=100带入计算可得7
19、B,编程题,for循环c次,s初值为a,没循环依次给s累加1,所以最后s累加了c次,s=a+c
20、C,基础题,考察计算机历史常识,图灵奖是计算机界最高奖。

二、问题求解

1、[NOIP-2014-J1-21]把M个同样的球放到N个同样的袋子里,允许有的袋子空着不放,问共有多少种不同的放置方法?(用K表示)。 例如,M=7,N=3时,K=8;在这里认为和是同一种放置方法。 问:M=8,N=5时,K=————
解析:数学题,考察组合数学应用,这里是球-盒子问题,球相同,盒子相同,可以为空,直接用公式求解:
P 1 8 + P 2 8 + P 3 8 + P 4 8 + P 5 8 = 1 + 4 + P 1 5 + P 2 5 + P 3 5 + P 1 4 + P 2 4 + P 3 4 + P 4 4 + P 1 3 + P 2 3 + P 3 3 = 1 + 4 + 1 + 2 + 2 + 1 + 2 + 1 + 1 + 1 + 1 + 1 = 18 P_1^8+P_2^8+P_3^8+P_4^8+P_5^8 =1+4+P_1^5+P_2^5+P_3^5+P_1^4+P_2^4+P_3^4+P_4^4+P_1^3+P_2^3+P_3^3 =1+4+1+2+2+1+2+1+1+1+1+1=18 P18+P28+P38+P48+P58=1+4+P15+P25+P35+P14+P24+P34+P44+P13+P23+P33=1+4+1+2+2+1+2+1+1+1+1+1=18

2、
[NOIP-2014-J1-22]如图所示,图中每条边上的数字表示该边的长度,则从A到E的最短距离是————
在这里插入图片描述

解析:算法题,考察图的单源点最短路径,可以用迪杰斯特拉算法求,不过题目比较简单,可以直接观察法找到一条最短路径是11,A-B-C-F-D-E

三、阅读程序

1、

#include <iostream>
using namespace std;
int main()
{
    int a, b, c, d, ans;
    cin >> a >> b >> c;
    d = a - b;
    a = d + c;
    ans    = a * b;
    cout << "Ans = " << ans << endl; 
        return(0);
}

输入:2 3 4

简单编程题,考察C++编程基础,算术运算符,表达式,直接计算可得结果是9

2、

#include <iostream>   
using namespace std;   
int fun(int n)    
{  
    if(n == 1)        
        return 1;      
    if(n == 2)        
        return 2;  
    return fun(n -2) - fun(n - 1);    
}   
int main()    
{  
    int n;      
    cin >> n;  
    cout << fun(n) << endl;     
    return 0;    
} 

输入:7
编程题,考察递归函数,打表可得
在这里插入图片描述

3、

#include <iostream>
#include <string>
using namespace std;
int main()
{
    string    st;
    int    i, len;
    getline( cin, st );
    len = st.size();
    for ( i = 0; i < len; i++ )
        if ( st[i] >= 'a' && st[i] <= 'z' )
            st[i] = st[i] - 'a' + 'A';
    cout << st << endl;
    return(0);
}

输入:Hello, my name is Lostmonkey.

编程题,考察字符串处理,题目是对输入字符串进行遍历,将所有的小写字母转为大写字母,然后输出,所以结果是:
HELLO, MY NAME IS LOSTMONKEY.

4、

#include <iostream>
using namespace std;
const int SIZE = 100;
int main()
{
    int    p[SIZE];
    int    n, tot, i, cn;
    tot = 0;
    cin >> n;
    for ( i = 1; i <= n; i++ )
        p[i] = 1;
    for ( i = 2; i <= n; i++ )
    {
        if ( p[i] == 1 )
            tot++;
        cn = i * 2;
        while ( cn <= n )
        {
            p[cn] = 0;
            cn += i;
        }
    }
    cout << tot << endl;
    return(0);
}

输入:30

解析:编程题,考察素数的朴素筛法,这里求的是1-n之间的所有素数的个数,将数组p的1-n个元素值初值设为1,通过判断p中下标不是素数的元素值设为0,剩余值为1的元素下标就都是素数。
输入:30
则依次枚举1-30内的素数可得:2,3,5,7,11,13,17,19,23,29,总共10个

四、完善程序

1、(数字删除)下面程序的功能是将字符串中的数字字符删除后输出

#include <iostream>
using namespace std;
int delnum( char *s )
{
    int i, j;
    j = 0;
    for ( i = 0; s[i] != '\0'; i++ )
        if ( s[i] < '0'   ①  s[i] > '9' )
        {
            s[j] = s[i];;
        }
    return();
}


const int SIZE = 30;
int main()
{
    char    s[SIZE];
    int len, i;
    cin.getline( s, sizeof(s) );
    len = delnum( s );
    for ( i = 0; i < len; i++ )
        cout <<;
    cout << endl;
    return(0);
}

编程题,考察字符串处理,题目是要去将字符串中的数字字符删除后然后输出,观察代码,显然delnum函数即是实现删除字符串中数字字符功能的,main函数中,输入字符串s,然后调用delnum函数,最后返回的是一个长度len,就是删掉数字字符后的字符串长度,因为紧接着就是按照len长度做循环,依次输出字符串的每一个字符,④s[i]

delnum函数对字符串进行就地处理,从左至右遍历,采用两个下标i,j,分别代表原字符串,和处理后的字符串下标,若字符不是数字,则直接按顺序将其覆盖到下标j处,然后j右移一位,最后j记录了处理后的字符串的长度,并返回j

2、(最大子矩阵和)给出m行n列的整数矩阵,求最大的子矩阵和(子矩阵不能为空)。

输入第一行包含两个整数m和n,即矩阵的行数和列数。之后m行,每行n个整数,描述整个矩阵。程序最终输出最大的子矩阵和。(最后一空4分,其余3分,共16分) 比如在如下这个矩阵中:
在这里插入图片描述
在这里插入图片描述

#include <iostream>
using namespace std;
const int SIZE = 100;
int matrix[SIZE + 1][SIZE + 1];
int rowsum[SIZE + 1][SIZE + 1]; /* rowsum[i][j]记录第i行前j个数的和 */
int m, n, i, j, first, last, area, ans;
int main()
{
    cin >> m >> n;
    for ( i = 1; i <= m; i++ )
        for ( j = 1; j <= n; j++ )
            cin >> matrix[i][j];
    ans = matrix   ①;
    for ( i = 1; i <= m; i++ );
        for ( i = 1; i <= m; i++ )
            for ( j = 1; j <= n; j++ )
                rowsum[i][j] =;
    for ( first = 1; first <= n; first++ )
        for ( last = first; last <= n; last++ )
        {;
            for ( i = 1; i <= m; i++ )
            {
                area +=;
                if ( area > ans )
                    ans = area;
                if ( area < 0 )
                    area = 0;
            }
        }
    cout << ans << endl;
    return(0);
}

算法题,考察动态规划,dp求解最大子矩阵和问题,该问题可以看成是二维的最大连续子序列和的问题,首先回顾一维数组的最大子序列和问题:
对数组a,d[i]表示以a[i]为结尾的最大子数组和,则
d[i] = max{d[i-1] + a[i], a[i]}=max{d[i-1], 0} + a[i]
这样,遍历一遍序列即可求出所有d[i],取最大值即可,时间复杂度为o(n)。
问题扩展到二维序列,也就是矩阵,则更复杂了,需要一些预处理工作,将问题转换为一维序列的情况。

①[1][1],初始化ans为矩阵的第一个元素,然后是构建rowsum数组,根据注释,row[i][j]记录的是矩阵的第i行的前j个数的和,这个是前序和数组,为了方便后面做数据压缩计算。②初始化rowsum数组的每一行的第0个元素值为0,rowsum[i][0]=0,③进行循环累加,计算每个rowsum[i][j]的值,③rowsum[i][j]=rowsum[i][j-1]+matrix[i][j]

first和last分别表示每次筛选的起止列,将matix数组的first-last之间的列压缩成一列由m个元素构成一维序列,序列的第i个元素a[i]是matix数组的第行的第first至第last个数的和,利用rowsum数组可以快速求得a[i]=rowsum[i][last]-rowsum[i][first-1],依次枚举每组first-last,做一维序列的最大子序列和,④初始化area=0,然后遍历,每次累加a[i],⑤rowsum[i][last]-rowsum[i][first-1],若大于ans则更新ans,同时若area为负数,则直接丢弃,重置为0,遍历完之后,求出所有的压缩序列的最大子序列和,其中的最大的即ans。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

严老师编程

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

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

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

打赏作者

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

抵扣说明:

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

余额充值