ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

NOIP-2012-J1-真题解析

2021-11-12 15:34:18  阅读:194  来源: 互联网

标签:NOIP 真题 int get J1 考察 ans include data


一、选择题

1、A,基础题,考察计算机硬件系统,计算机主机核心包括内存和处理器,缺少内存,将无法启动
2、B、队列是先进先出的线性表
3、A,基础题,考察计算机常识
4、B,基础题,考察进制转换,9A的二进制表示是1001 1010,转8进制是232
5、C,基础题,考察计算机基础,常见的操作系统,C是图形处理软件,是应用软件
6、C,数据结构题,考察二叉树的遍历,C选项的话,无法确定这颗二叉树,前后是矛盾的
7、B,基础题,常见CPU
8、C,算法题,考察冒泡排序算法,冒泡排序是每次比较相邻的两个元素,每一次交换也是交换相邻的两个元素,所以每次交换只减少一个逆序对,枚举序列中的逆序对的个数为10
9、A,基础题,考察计算机历史常识
10、A
11、B,基础题,考察计算机基础,多媒体技术,矢量图的相关概念
12、D,数据结构题,考察栈的出栈入栈序列,代入选项模拟可得D
13、B,基础题,考察计算机网络基础,浏览器
14、C,基础题,考察计算机网络常用应用层协议,电子邮件的服务协议,POP3
15、C,算法题,考察分治算法的基本概念
16、D,基础题,考察计算机硬件知识,CPU地址总线与寻址空间,理论上寻址空间等于总线长度能表示的二进制数据最大范围,32位总线,即2^32=4G
17、C,基础题,考察计算机网络,无线局域网,蓝牙和wifi是常见的无线局域网设备
18、A,基础题,考察递归程序的实现,递归程序的递归执行过程由操作系统分配的栈来实现,如果递归层数过多,会造成栈空间溢出
19、C,基础题,枚举可得1+2+…+9-32-31=36
20、B,基础题,科学常识

二、问题求解

1、每个整点的横纵坐标都是整数,要么是奇数,要么是偶数,只有(奇,偶),(偶,奇),(奇,奇),(偶,偶)4种情况,假设任意两个点的坐标分别是(x1,y1),(x2,y2),则其连线中点坐标是((x1+x2)/2, (y1+y2)/2),除了(奇数+偶数)不能被2整除,其他组合都能被2整除,显然(奇,偶),(偶,奇),(奇,奇),(偶,偶)这4种任意两种坐标的连线中点都不是整点,然后再加上4种中的任意一种坐标,比如(偶,偶),就能找到至少有两个点连线中点是整点,所以答案是5

2、组合数学题,先规定一种类型的5个选手做圆排列,比如5名大陆选手,圆排列有5!/4=24种,每一种排列,都有5个空,可以用来插入5个港澳选手,总共有5!种插入方法,根据乘法原理,总共有24×5!=2880种

三、阅读程序

1、

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

编程题,直接代入输入即可得结果为10

2、

#include <iostream>
using namespace std;
int n,i,ans;
int main()
{
    cin>>n;
    ans=0;
    for(i=1;i<=n;i++)
        if(n%i==0) ans++;
    cout<<ans<<endl;
    return 0;    
}

此题求18的约数的个数,依次枚举可得:1,2,3,6,9,18,共6个

3、

#include <iostream>
using namespace std;
int n,i,j,a[100][100];
int solve(int x,int y)
{
    int u,v;
    if(x==n) return a[x][y];
    u=solve(x+1,y);
    v=solve(x+1,y+1);
    if(u>v) return a[x][y]+u;
    else return a[x][y]+v;    
}
int main()
{
    cin>>n;
    for(i=1;i<=n;i++)
        for(j=1;j<=i;j++) cin>>a[i][j];
    cout<<solve(1,1)<<endl;
    return 0;    
}

考察递归函数求解,打表可得结果14
在这里插入图片描述
4、

#include <iostream>
#include <string>
using namespace std;
int n,i,j,ans;
string s;
char get(int i)
{
    if(i<n) return s[i];
    else return s[i-n];    
}
int main()
{
    cin>>s;
    n=s.size();
    ans=0;
    for(i=1;i<=n-1;i++)
    {
        for(j=0;j<=n-1;j++)
            if(get(i+j)<get(ans+j))
            {
                ans=i;
                break;    
            }
            else if(get(i+j)>get(ans+j)) break;
    }
    for(j=0;j<=n-1;j++) cout<<get(ans+j);
    cout<<endl;
    return 0;    
}

首先把get(i)的取值列表列出来,代码中多次调用get(i)函数
在这里插入图片描述
然后打表得到ans=7,然后输出get(ans+j),输出get(7)-get(14),为ACBBADAD
在这里插入图片描述

三、完善程序

1、(坐标统计)输入n个整点在平面上的坐标。对于每个点,可以控制所有位于它左下方的点(即x、y坐标都比它小),它可以控制的点的数目称为“战斗力”。依次输出每个点的战斗力,最后输出战斗力最高的点的编号(如果若干个点的战斗力并列最高,输出其中最大的编号)。

#include <iostream>
using namespace std;
const int SIZE =100;
int x[SIZE],y[SIZE],f[SIZE];
int n,i,j,max_f,ans;
int main()
{
    cin>>n;
    for(i=1;i<=n;i++) cin>>x[i]>>y[i];
    max_f=0;
    for(i=1;i<=n;i++)
    {
        f[i]= [  ①   ];
        for(j=1;j<=n;j++)
        {
            if(x[j]<x[i] && [   ②    ])
            [      ③      ] ;
        }
        if( [     ④       ])
        {
            max_f=f[i];
            [    ⑤    ];    
        }
    }
    for(i=1;i<=n;i++) cout<<f[i]<<endl;
    cout<<ans<<endl;
    return 0;    
}

简单模拟算法,依次统计每个点的战斗力,比较得到最大战斗力的点,若相同,则取最新的,也就是编号最高的
① 0,初始化战斗力都为0
② y[j]<y[i]
③ f[i]++
④ f[i]>=max_f
⑤ ans = i

2、(排列数)输入两个正整数n,m(1<n<20,1<m<n),在1~n中任取m个数,按字典序从小到大输出所有这样的排列。 例如:
输入:3 2
输出:
1 2
1 3
2 1
2 3
3 1
3 2

#include <iostream>
#include <cstring>
using namespace std;
const int SIZE =25;
bool used[SIZE];
int data[SIZE];
int n,m,i,j,k;
bool flag;
int main()
{
    cin>>n>>m;
    memset(used,false,sizeof(used));
    for(i=1;i<=m;i++)
    {
        data[i]=i;
        used[i]=true;    
    }
    flag=true;
    while(flag)
    {
        for(i=1;i<=m-1;i++) cout<<data[i]<<" ";
        cout<<data[m]<<endl;
        flag= [    ①    ] ;
        for(i=m;i>=1;i--)
        {
            [    ②     ];
            for(j=data[i]+1;j<=n;j++)
                if(!used[j])
                {
                    used[j]=true;
                    data[i]=[    ③  ] ;
                    flag=true;
                    break;    
                }
            if(flag)
            {
                for(k=i+1;k<=m;k++)
                    for(j=1;j<= [   ④   ];j++)
                    if(!used[j])
                    {
                        data[k]=j;
                        used[j]=true;
                        break;
                    }
                [     ⑤   ];
            }
        }
    }
    return 0;    
}

目中给的例子太弱了,通常的n个数取m个数排列,要按字典大小顺序输出,如图所示,我们按顺序枚举,每次都需要从右往左找到第一个可以变大的数,比如Ax可以变大为Ay,然后还需要将Ay右边的数重新按大小顺序排序依次枚举出来。
比如n=5,m=4,第一个排列肯定是1,2,3,4,然后从右边开始,第一个4只能变大为5,将5排上,同时将4释放,此刻,5右边没有数了。继续下一轮,第一个能变大的数是3,将3变大为4,同时将3释放,然后3右边还有一个数位,这个数将从剩余的未排上的数里面按从小到大顺序依次选取排列,即3,5,依次类推,直到从右至左遍历完每一个可以变大的数的变大情况。
在这里插入图片描述
while循环的第一部分就是输出当前找到的一个排列
① false,flag是表示当前是否找到一个合法的排列,初值是false,②used[data[i]]=false,从右至左找变大的数替换,首先将待替换的数data[i]释放,然后从data[i]+1至n,选取第一个未选用的数排上来放在data[i]的位置i上,③ j,此刻将flag置为true,表示找到一个新的排列方案,然后如果i右边还有数,则i右边的位置,即i+1到m,用剩余的未选用的数按从小到大顺序依次填上,④ n,⑤ break跳出循环,直接进入下一轮外层while循环的头部,输出上一轮找到的排列方案。

标签:NOIP,真题,int,get,J1,考察,ans,include,data
来源: https://blog.csdn.net/weixin_46966772/article/details/121288389

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有