admin 管理员组文章数量: 1086019
2024年12月29日发(作者:switch线路图)
NOIP提高组初赛历年试题及答案(完善题篇)
完善程序,每年两题,每题每空
2-4
分,共
28
分。
【数学题目】
1
、变量赋初值,如果以后用到的是加减运算,则赋初值
0
;如果以后用到的是
乘除运算,则赋初值为
1
。
2
、循环条件的填空,分析表达式的规律,看表达式中的最后一项的值是否到了
第
m
项或者是第
n
项,如果到了,则在循环中的第二个表达式中用到的是
i<=
或者
i>=
。
3
、循环条件中如果用的是
while
语句,则循环变量的初值应该在
while
的外面
定义和赋初值,在循环语句中必须给变量自加或者是自减,即
i++
或
i--
。
【字符串题目】
1
、把一个数字字符转变成对应的数值的格式是:
ch=’1’-‘0’;
把大写字母转变为小
写字母的格式:
ch=ch+32;
把小写字母转变为大写字母的格式为:
ch=ch-32
。
2
、区分好字符数组中的指针和指针所指的值的关系。在循环语句中,当指针往
后走一个位置的时候,用的是指针的自加,而不是指针所指的值的自加。
【结构体题目】
1
、注意定义结构体变量时的格式。
2
、结构体中成员的调用格式。结构体中的成员分为多种类型,调用结构体中的
成员,使用的是
“.”
或者是
“—>”
运算符。
3
、如果返回的是结构体的话,函数的返回类型必须是结构体类型。调用函数的
格式中,调用的若是结构体数组,则只用写结构体数组名。
【函数题目】
1
、看函数的返回类型,函数的返回类型必须和
return
语句返回的表达式的类型
一致。
2
、函数的调用的情况,函数调用时只用写函数的名称,以及函数的参数。如:
f1(x)
和
f2(x,y)
。
【数组题目】
1
、求一个数值数组中的所有值的平均值和把大于或者小于平均值的数放到另外
一个数组中。首先定义一个变量来存放平均值,如果变量
avg
已经定义但是没
有赋初值,那么这个空填写的内容的为:
avg=0;
2
、求平均值时有两种方法,如果在
for
语句的后面有
avg=avg/N;
则第二个空一
般的填写时
avg+=s[i];
如果说没有
avg=avg/N;
则填写的是:
avg+=s[i]/N
。
3
、二维数组遍历时,使用的是两个循环,使用的是循环的嵌套使用,第二个循
环填写的内容为:
j=0
。
NOIP2011-1.
大整数开方(同普及组
2011-2
)
输入一个正整数n(1≤n≤10^100),试用二分法计算它的平方根的整数部分。
#include
#include
usingnamespacestd;
constintSIZE=200;
structhugeint{
intlen,num[SIZE];
};
//其中len表示大整数的位数;num[1]表示个位,num[2]表示十位,以此类推
hugeinttimes(hugeinta,hugeintb)
//
计算大整数
a
和
b
的乘积
{
inti,j;
hugeintans;
memset(,0,sizeof());
for(i=1;i<=;i++)
for(j=1;j<=;j++)
[i+j-1]+=[i]*[j];
for(i=1;i<=+;i++){
[i+1]+=[i]/10;
[i]%=10;
}
if([+]>0)
=+;
else
=+-1;
returnans;
}
hugeintadd(hugeinta,hugeintb)
//
计算大整数
a
和
b
的和
{
inti;hugeintans;
memset(,0,sizeof());
if(>)
=;
else
=;
for(i=1;i<=;i++){
[i]+=[i]+[i];
[i+1]+=[i]/10;
[i]%=10;
}
if([+1]>0)
++;
returnans;
}
hugeintaverage(hugeinta,hugeintb)
//计算大整数a和b的平均数的整数部分
{
inti;
hugeintans;
ans=add(a,b);
for(i=;i>=2;i--){
[i-1]+=([i]%2)*10;
[i]/=2;
}
[1]/=2;
if([]==0)
--;
returnans;
}
hugeintplustwo(hugeinta)
//
计算大整数
a
加
2
之后的结果
{
inti;
hugeintans;
ans=a;
[1]+=2;
i=1;
while((i<=)&&([i]>=10)){
[i+1]+=[i]/10;
[i]%=10;
i++;
}
if([+1]>0)
++;
returnans;
}
boolover(hugeinta,hugeintb)
//
若大整数
a>b
则返回
true
,否则返回
false
{
inti;
if(<)
returnfalse;
if(>)
returntrue;
for(i=;i>=1;i--){
if([i]<[i])
returnfalse;
if([i]>[i])
returntrue;
}
returnfalse;
}
intmain()
{
strings;
inti;
hugeinttarget,left,middle,right;
cin>>s;
memset(,0,sizeof());
=();
for(i=1;i<=;i++)
[i]=s[-i]-'0';
memset(,0,sizeof());
=1;
[1]=1;
right=target;
do{
middle=average(left,right);
if(over(times(middle,middle),target))
right=middle;
else
left=middle;
}while(!over(plustwo(left),right));
for(i=;i>=1;i--)
cout<<[i];
return0;
}
NOIP2011-2.
笛卡尔树
对于一个给定的两两不等的正整数序列,笛卡尔树是这样的一棵二叉树:首先,
它是一个最小堆,即除了根结点,每个节点的权值都大雨父节点的权值;其次,
它的中序遍历恰好就是给定的序列。例如,对于序列
7
、
2
、
12
、
1
、
10
、
5
、
15
、
3
,下图就是一棵对应的笛卡尔树。现输入序列的规模
n
(
1≤n<100
)和序列的
n
个元素,试求其对应的笛卡尔树的深度
d
(根节点深度为
1
),以及有多少个叶
子节点的深度为
d
。
#include
usingnamespacestd;
constintSIZE=100+5;
constintINFINITY=1000000;
intn,a[SIZE],maxDeep,num;
voidsolve(intleft,intright,intdeep)
{
inti,j,min;
if(deep>maxDeep){
maxDeep=deep;
num=1;
}
elseif(deep==maxDeep)
num++;
min=INFINITY;
for(i=left;i<=right;i++)
if(min>a[i]){
min=a[i];
j=i;
}
if(left solve(left,j–1,deep+1); if(j solve(j+1,right,deep+1); } intmain() { inti; cin>>n; for(i=1;i<=n;i++) cin>>a[i]; maxDeep=0; solve(1,n,1); cout< return0; } NOIP2012-1. 排列数(同普及组 2012-2 ) 输入两个正整数 n,m(1≤n≤20,1≤m≤n) ,在 1~n 中任取 m 个数,按字典序 从小到大输出所有这样的排列。例如 输入 : 32 输出 : 12 13 21 23 31 32 #include #include usingnamespacestd; constintSIZE=25; boolused[SIZE]; intdata[SIZE]; intn,m,i,j,k; boolflag; intmain() { 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< cout< flag=false; for(i=m;i>=1;i--){ used[data[i]]=false; for(j=data[i]+1;j<=n;j++)if(!used[j]){ used[j]=true; data[i]=j; flag=true; break; } if(flag) { for(k=i+1;k<=m;k++) for(j=1;j<=n;j++)if(!used[j]){ data[k]=j; used[j]=true; break; } break; } } } } NOIP2012-2. 新壳栈 小 Z 设计了一种新的数据结构 “ 新壳栈 ” 。首先,它和传统的栈一样支持压入、弹 出操作。此外,其栈顶的前 c 个元素是它的壳,支持翻转操作。其中, c>2 是 一个固定的正整数,表示壳的厚度。小 Z 还希望,每次操作,无论是压入、弹 出还是翻转,都仅用与 c 无关的常数时间完成。聪明的你能帮助她编程实现 “ 新 壳栈 ” 吗? 程序期望的实现效果如以下两表所示。其中,输入的第一行是正整数c,之后每 行输入都是一条指令。另外,如遇弹出操作时栈为空,或翻转操作时栈中元素不 足c个,应当输出相应的错误信息。 #include usingnamespacestd; constintNSIZE=100000,CSIZE=1000; intn,c,r,tail,head,s[NSIZE],q[CSIZE]; // 数组 s 模拟一个栈, n 为栈的元素个数 // 数组 q 模拟一个循环队列, tail 为队尾的下标, head 为队头的下标 booldirection,empty; intprevious(intk) { if(direction) return((k+c-2)%c)+1; else return(k%c)+1; } intnext(intk) { if(direction) return(k%c)+1; else return((k+c-2)%c)+1; } voidpush() { intelement; cin>>element; if(next(head)==tail){ n++; s[n]=q[tail]; tail=next(tail); } if(empty) empty=false; else head=next(head); q[head]=element; } voidpop() { if(empty){ cout<<"Error:thestackisempty!"< return; } cout< if(tail==head) empty=true; else{ head=previous(head); if(n>0){ tail=previous(tail); q[tail]=s[n]; n--; } } } voidreverse() { inttemp; if(next(head)==tail){ direction=!direction; temp=head; head=tail; tail=temp; } else cout<<"Error:lessthan"< } intmain() { cin>>c; n=0; tail=1; head=1; empty=true; direction=true; do{ cin>>r; switch(r){ case1:push();break; case2:pop();break; case3:reverse();break; } }while(r!=0); return0; } NOIP2013-1. 序列重排 全局数组变量 a 定义如下: ConstintSIZE=100; inta[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): voidswap1(intp) { inti,j,b[SIZE]; for(i=1;i<=p;i++) b[n–p+i]=a[i]; for(i=p+1;i<=n;i++) b[i-p]=a[i]; for(i=1;i<=n;i++) a[i]=b[i]; } 我们也可以用时间换空间,使用时间复杂度为O(n2)、空间复杂度为O(1)的算 法: voidswap2(intp) { inti,j,temp; for(i=p+1;i<=n;i++){ temp=a[i]; for(j=i;j>=i–p+1;j--) a[j]=a[j-1]; a[i–p]=temp; } } 事实上,还有一种更好的算法,时间复杂度为 O(n) 、空间复杂度为 O(1) : voidswap3(intp) { intstart1,end1,start2,end2,i,j,temp; start1=1; end1=p; start2=p+1; end2=n; while(true){ i=start1; j=start2; while((i<=end1)&&(j<=end2)){ temp=a[i]; a[i]=a[j]; a[j]=temp; i++; j++; } if(i<=end1) start1=i; elseif(j<=end2){ start1=i endl=j–1 start2=j; } else break; } } NOIP2013-2. 两元序列 试求一个整数序列中,最长的仅包含两个不同整数的连续子序列。如有多个子序 列并列最长,输出任意一个即可。例如,序列“131”中,有 两段满足条件的最长子序列,长度均为7,分别用下划线和上划线标出。 #include usingnamespacestd; intmain() { constintSIZE=100; intn,i,j,a[SIZE],cur1,cur2,count1,count2, ans_length,ans_start,ans_end; //cur1,cur2 分别表示当前子序列中的两个不同整数 //count1,count2分别表示cur1,cur2在当前子序列中出现的次数 cin>>n; for(i=1;i<=n;i++) cin>>a[i]; i=1; j=1; //i,j分别表示当前子序列的首尾,并保证其中至多有两个不同整数 while((j<=n)&&(a[j]==a[i])) j++; cur1=a[i]; cur2=a[j]; count1=j-1 count2=1; ans_length=j-i+1;
版权声明:本文标题:NOIP提高组初赛历年试题及答案完善题篇(56页) 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.roclinux.cn/p/1735570243a1677035.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论