2013年信息学奥赛NOIP普及组
初赛
更早
2023-08-21 18:33:22
105次
一、单选题
二、填空题
#include <iostream>
using namespace std;
int main()
{
const int SIZE = 100;
int height[SIZE], num[SIZE], n, ans;
cin>>n;
for (int i = 0; i < n; i++) {
cin>>height[i];
num[i] = 1;
for (int j = 0; j < i; j++) {
if ((height[j] < height[i]) && (num[j] >= num[i]))
num[i] = num[j]+1;
}
}
ans = 0;
for (int i = 0; i < n; i++) {
if (num[i] > ans) ans = num[i];
}
cout<<ans<<endl;
}输入:
6
2 5 3 11 12 4
输出:
【知识点】 信息学NOIP普及组
#include <iostream>
using namespace std;
int main()
{
const int SIZE = 100;
int n, f, i, left, right, middle, a[SIZE];
cin>>n>>f;
for (i = 1; i <= n; i++)
cin>>a[i];
left = 1;
right = n;
do {
middle = (left + right) / 2;
if (f <= a[middle])
right = middle;
else
left = middle + 1;
} while (left < right);
cout<<left<<endl;
return 0;
}输入:
12 17 2 4 6 9 11 15 17 18 19 20 21 25
输出:
【知识点】 信息学NOIP普及组
某系统自称使用了一种防窃听的方式验证用户密码。密码是n个数 s1, s2, … , sn ,均为0或1。该系统每次随机生成n个数a1, a2, … , an,均为0或1,请用户回答(s1a1+s2a2+… +snan)除以2的余数。如果多次的回答总是正确,即认为掌握密码。该系统认为, 即使 问答的过程被泄露, 也无助于破解密码—— 因为用户并没有直接发送密码。
然而, 事与愿违。例如,当n= 4 时, 有人窃听了以下 5 次问答:
就破解出了密码 s1= ,s2= ,s3= ,s4= 。
【知识点】 信息学NOIP普及组
三、简答题
完善程序:(二叉查找树)二叉查找树具有如下性质:每个节点的值都大于其左子树上所有节点的 值、小于其右子树上所有节点的值。 试判断一棵树是否为二叉查找树。
输入的第一行包含一个整数n,表示这棵树有n个顶点, 编号分别为1,2, … ,n,其 中编号为1的为根结点。之后的第i行有三个数value,left_child,right_child,分别表示 该节点关键字的值、左子节点的编号、右子节点的编号;如果不存在左子节点或右子节 点,则用0代替。输出1表示这棵树是二叉查找树,输出0则表示不是。
#include <iostream>
using namespace std;
const int SIZE = 100;
const int INFINITE = 1000000;
struct node {
int left_child, right_child, value;
};
node a[SIZE];
int is_bst(int root, int lower_bound, int upper_bound)
{
int cur;
if (root == 0)
return 1;
cur = a[root].value;
if ((cur > lower_bound) && ( (1) ) && //(3 分)
(is_bst(a[root].left_child, lower_bound, cur) == 1) &&
(is_bst( (2) , (3) , (4) ) == 1)) //(3 分,3 分,3 分)
return 1;
return 0;
}
int main()
{
int i, n;
cin>>n;
for (i = 1; i <= n; i++)
cin>>a[i].value>>a[i].left_child>>a[i].right_child;
cout<<is_bst( (5) , -INFINITE, INFINITE)<<endl; //(2 分)
return 0;
}
【知识点】 信息学NOIP普及组
完善程序:(序列重排)全局数组变量a定义如下:
const int SIZE = 100;
int a[SIZE], n;
它记录着一个长度为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):
void swap1(int p)
{
int i, j, b[SIZE];
for (i = 1; i <= p; i++)
b[ (1) ] = a[i]; //(3 分)
for (i = p + 1; i <= n; i++)
b[i - p] = (2) ; //(3 分)
for (i = 1; i <= (3) ; i++) //(2 分)
a[i] = b[i];
}
我们也可以用时间换空间,使用时间复杂度为O(n2)、空间复杂度为O(1)的算法:
void swap2(int p)
{
int i, j, temp;
for (i = p + 1; i <= n; i++) {
temp = a[i];
for (j = i; j >= (4) ; j--) //(3 分)
a[j] = a[j - 1];
(5) = temp; //(3 分)
}
}
【知识点】 信息学NOIP普及组



