NOIP 提高组 初赛 四、阅读程序写结果 习题集(三)NOIP2002-NOIP2003
1.第八届(NOIP2002)
问题(原文是pascal,按题意,本人改写成C,C++版本):
1.
//2002.3.1
#include <stdio.h>
#include <string.h>
int main(){
int i,n,jr,jw,jb;
char ch1;
char ch[22];
scanf("%d",&n);
scanf("%s",ch);
jr=0;
jw=n-1;
jb=n-1;
while(jr<=jw){
if(ch[jw]=='R'){
ch1=ch[jr];
ch[jr]=ch[jw];
ch[jw]=ch1;
jr++;
}else if(ch[jw]=='W'){
jw--;
}else{
ch1=ch[jw];
ch[jw]=ch[jb];
ch[jb]=ch1;
jw--;
jb--;
}
}
printf("%s\n",ch);
return 0;
}
//输入:
//10
//RBRBWWRBBR
2.
//2002.3.2
//将pascal转换成C、C++过程中,还出现了些小纰漏,不过读pascal代码能力更进步了.
#include <stdio.h>
int main(){
int i,j,s,sp1;
int p;
int a[11];
sp1=1;
a[1]=2;
j=2;
while(sp1<10){
j++;
p=1;
for(i=2;i<=j-1;i++)
if(j%i==0)
p=0;
if(p){//开始将该段if放在for循环中,答案不对,后将该段if移出for循环,答案正确
sp1++;
a[sp1]=j;
}
}
j=2;
p=1;
while(p){
s=1;
for(i=1;i<=j;i++)
s*=a[i];
s++;
for(i=2;i<=s-1;i++)
if(s%i==0)
p=0;
j++;
}
printf("%d\n",s);
return 0;
}
3.
//2002.3.3
#include <stdio.h>
#include <math.h>
int main(){
float d1,d2,x,min;
min=10000;
x=3;
while(x<15){
d1=sqrt(9+(x-3)*(x-3));
d2=sqrt(36+(15-x)*(15-x));
if((d1+d2)<min)
min=d1+d2;
x+=0.001;
}
printf("%8.2f\n",min);
return 0;
}
问题解答:
1.字符串问题,总体比较简单,信心足,根据输入数据,跟踪程序,记录相关数据信息:
答案:RRRRWWBBBB
1中等
2.跟着程序跑一段,很快发现数组a是存储质数的。
a[1]=2
a[2]=3
a[3]=5
a[4]=7
a[5]=11
a[6]=13
a[7]=17
a[8]=19
a[9]=23
a[10]=29
第二个while循环是判断s值是否是质数,非质数,跳出循环,打印s值。
s=7
s=31
s=211
s=2311
s=30031
本人就没往下算了,倒在黎明前啊。
不过30031非质数也是难判断,编了程序才发现30031=59*509,考试中算不出啊,
答案:30031
2难,难在判断非质数。
3.自个弄了半天,没对上答案,具体分析也就不说了,参考http://www.docin.com/p-270931446.html
做个纠正,交点x=7.000。
过程如下:
d1=sqrt(9+(x-3)*(x-3))=sqrt((0-3)*(0-3)+(x-3)*(x-3))
d1表示(x,0)与(3,3)两点间距离
d2=sqrt(36+(15-x)*(15-x))=sqrt((0-6)*(0-6)+(x-15)*(x-15))
d2表示(x,0)与(15,6)两点间距离
思考过程如图所示(两点之间最短距离是直线):
min=(15-3)^2+(6-(-3))^2=15.00
答案:15.00
3难
1中等2难3难
2.第九届(NOIP2003)
问题(原文是pascal,按题意,本人改写成C,C++版本):
1.//2003.4.1
#include <stdio.h>
int main(){
long long a,b,c,d,sum;
int a1,b1,c1,d1;
scanf("%d%d%d%d",&a1,&b1,&c1,&d1);
a=a1;
b=b1;
c=c1;
d=d1;
a%=23;
b%=28;
c%=33;
sum=a*5544+b*14421+c*1288-d;//摘抄文件是1228,后搜索网络发现是1288
sum+=21252;
sum%=21252;
if(sum==0)
sum=21252;
printf("%lld\n",sum);
return 0;
}
//输入:283 102 23 320
2.
//2003.4.2
#include <stdio.h>
int main(){
const int u[4]={0,5,3,1};
const int v[4]={0,7,6,5};
int a,b,c,d,e,f,x,y,z;
scanf("%d%d%d%d%d%d",&a,&b,&c,&d,&e,&f);
z=f+e+d+(c+3)/4;
y=5*d+u[c%4-1];
if(b>y){
z=z+(b-y+8)/9;
x=((b-y+8)/9*9-(b-y))*4+11*e+v[c%4-1];
}else
x=(y-b)*4+11*e+v[c%4-1];
if(a>x)
z=z+(a-x+35)/36;
printf("%d\n",z);
return 0;
}
//输入:4 7 9 20 56 47
3.
//2003.4.3
//原文有残缺,上网搜索
#include <stdio.h>
int m,n;
int mark;
int test(int m,int n){
int i,p;
int flag;
int ans;
m--;
i=0;
flag=0;
for(p=2*n;p>=n+1;p--){
i=(i+m)%p;
if(i<n){//此处原文if(i
flag=1;
ans=0;
break;
}
}
if(!flag)
ans=1;
return ans;
}
int main(){
scanf("%d",&n);
m=1;
mark=0;
do{
if(test(m,n)==1){
printf("%d\n",m);
break;
}
m++;
}while(mark==0);//此处原文until mark
return 0;
}
//输入:7
4.
//2003.4.4
#include <stdio.h>
int main(){
int m,n,i,j;
int p[20],w[20],a[20],b[20];
scanf("%d",&n);
m=0;
for(i=0;i<=n-1;i++){
scanf("%d",&p[i]);
b[i]=1;
}
for(i=0;i<=n-1;i++){
if(i>0)
a[m]=p[i]-p[i-1];
else
a[m]=p[i];
m++;
while(m>1&&a[m-1]==0){
m--;
b[m]=1;
}
if(m>0)
w[i]=b[m-1];
else
w[i]=b[0];
a[m-1]--;
for(j=0;j<=m-1;j++)
b[j]++;
while(m>1&&a[m-1]==0){
m--;
b[m]=1;
}
}
for(i=0;i<=n-1;i++)
printf("%d ",w[i]);
printf("\n");
return 0;
}
//输入:9
//4 6 6 6 6 8 9 9 9
问题解答:
1.代码比较短的题目,要么难在递归,要么难在数学。
sum=(7*5544+18*14421+23*1288-320+21252)%21252
看到这,马上就不想算,有没简便的方法,突然发现14421,5544,1288好像有联系。
21252-14421=6831
6831-5544=1287
立马改造上式
sum=(18*(5544+14421+1287)-11*5544+18*1+5*1288-320+21252)%21252
sum=(-11*5544+18*1+5*1288-320)%21252
sum=(-60984+18+6440-320)%21252等价于sum=(21252*3-60984+18+6440-320)%21252
sum=8910%21252
sum=8910.
答案:8910
1简单
2.顺着程序执行,很快就能得到答案
中间过程如下:
z=126
y=100
7>100
else
x=988
4>988
执行printf语句。
答案:126
2简单
3.程序意思很快能看懂,但手工算却算不出。搜索网络:
受https://zhidao.baidu.com/question/326602498.html启发开始研究约瑟夫问题,
这两段可以大致推测,这道题的题意是改编版的约瑟夫问题,即有N个好人,N个坏人,好人编号1~N,坏人编号N+1~2*N,求最小的M使先出圈的N个人都是坏人。
找到http://blog.sina.com.cn/s/blog_644817fd0100wo35.html可惜是程序算出。
研究手工算法。
暂无办法,机器算出的答案是1872。
3难
4.程序块位置敲错,以及没注意到该程序有两行输入,折腾了好半天,一直以为题目有误,结果题目没有问题。
重新开始做。一直觉得b[i]=1;有点怪,应该是b[i]=0;不过经验证,题目无误。
程序难在比较繁,一不小心就容易出错,思路简单,按部就班。
程序执行过程如下:
答案:1 1 2 4 5 1 1 3 9(空格分隔)
2016-12-15 21:21
4难