NOIP 提高組 初賽 四、閱讀程序寫結果 習題集(二)NOIP2000-NOIP2001
1.第六屆(NOIP2000)
問題(原文是pascal,按題意,本人改寫成C,C++版本):
1.
//NOIP2000 3.1#include <stdio.h>
#include <math.h>
const int n=7,m=6;
float disp(int x1,int y1,int x2,int y2){
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
int main(){
int i,j,x0,y0,x1,y1,x2,y2;
float d;
int p;
int g[n+1][m+1];
for(i=0;i<=n;i++)
for(j=0;j<=m;j++)
g[i][j]=0;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
g[x1][y1]=1;
g[x2][y2]=1;
p=1;
while(p){
p=0;
d=disp(x1,y1,x2,y2);
x0=x1;
y0=y1;
for(i=4;i<=n;i++)
for(j=0;j<=m;j++)
if(d>disp(i,j,x2,y2)&&g[i][j]==0){
d=disp(i,j,x2,y2);
x0=i;
y0=j;
}
if(x0!=x1||y0!=y1){
x1=x0;
y1=y0;
p=1;
g[x1][y1]=1;
}
d=disp(x1,y1,x2,y2);
x0=x2;
y0=y2;
for(i=0;i<=3;i++)
for(j=0;j<=m;j++)
if(d<disp(x1,y1,i,j)&&g[i][j]==0){
d=disp(x1,y1,i,j);
x0=i;
y0=j;
}
if(x0!=x2||y0!=y2){
x2=x0;
y2=y0;
p=1;
g[x2][y2]=1;
}
}
printf("%d %d %d %d\n",x1,y1,x2,y2);
return 0;
}
//輸入7 6 0 0
2.
//NOIP2000 3.2
#include <stdio.h>
int main(){
int i,j,L,n,k,s,t;
int b[11];
scanf("%d%d",&L,&n);
s=L;
k=1;
t=L;
if(n>L){
while(s<n){
k++;
t*=L;
s+=t;
}
s-=t;
n=n-s-1;
for(i=1;i<=10;i++)
b[i]=0;
j=11;
while(n>0){
j--;
b[j]=n%L;
n/=L;
}
for(i=10-k+1;i<=10;i++)
printf("%c",'A'+b[i]);
}else
printf("%c\n",'A'+n-1);
return 0;
}
//輸入:4 167
問題解答:
1.
閱讀跟蹤程序,可以發現:
for(i=4;i<=n;i++)
for(j=0;j<=m;j++)
if(d>disp(i,j,x2,y2)&&g[i][j]==0){
d=disp(i,j,x2,y2);
x0=i;
y0=j;
}
是找最小的長度。
for(i=0;i<=3;i++)
for(j=0;j<=m;j++)
if(d<disp(x1,y1,i,j)&&g[i][j]==0){
d=disp(x1,y1,i,j);
x0=i;
y0=j;
}
是找最大的長度。
思考過程如圖所示:
(x1,y1)0,(x2,y2)0表示初始值。
(x1,y1)1,(x2,y2)1表示第一次循環後的值。
(x1,y1)2,(x2,y2)2表示第二次循環後的值。
依次類推,一共會進行8次循環,第6次找到(x2,y2)6值,第7次找到(x1,y1)7值。第8次p=0。
答案:4 3 0 2
1難,涉及矩陣,空間的變換,開始需要順着程序跟蹤,弄明白意思後,可以畫二維圖進行思考。
2016-12-13
2.執行過程如下:
答案:BBAC
1難2簡單
2.第七屆(NOIP2001)
問題(原文是pascal,按題意,本人改寫成C,C++版本):
1.
//NOIP2001 3.1
#include <stdio.h>
int ack(int m,int n){
if(m==0)
return n+1;
else if(n==0)
return ack(m-1,1);
else
return ack(m-1,ack(m,n-1));
}
int main(){
printf("%d\n",ack(3,4));
}
2.
//2001.3.2
#include <stdio.h>
int main(){
int p,q,s,t;
scanf("%d",&p);
for(q=p+1;q<=2*p;q++){
t=0;
s=(p*q)%(q-p);
if(s==0){
t=p+q+(p*q)/(q-p);
printf("%4d",t);
}
}
}
//輸入:12
//輸出:
3.
//2001.3.3
#include <stdio.h>
int main(){
int i,j,h,m,n,k;
int b[11];
scanf("%d",&n);
for(i=1;i<=10;i++){
m=n;
j=11;
while(m>0){
j--;
b[j]=m%10;
m/=10;
}
for(h=j;h<=10;h++)
n+=b[h];
}
printf("%d\n",n);
return 0;
}
//輸入:1234
//輸出:
4.
//2001.3.4
#include <stdio.h>
int main(){
int x,y1,y2,y3;
scanf("%d",&x);
y1=0;
y2=1;
y3=1;
while(y2<=x){
y1++;
y3+=2;
y2+=y3;
}
printf("%d\n",y1);
return 0;
}
//輸入:23420
//輸出:
問題解答:
1.
思考過程如下:
ack(0,0)=1
ack(0,1)=2
ack(0,2)=4
ack(0,3)=4
ack(0,4)=5
ack(1,0)=ack(0,1)=2
ack(1,1)=ack(0,ack(1,0))=ack(0,2)=3
ack(1,2)=ack(0,ack(1,1))=ack(0,3)=4
ack(1,3)=ack(0,ack(1,2))=ack(0,4)=5
ack(1,4)=ack(0,ack(1,3))=ack(0,5)=6
ack(2,0)=ack(1,1)=3
ack(2,1)=ack(1,ack(2,0))=ack(1,3)=5
ack(2,2)=ack(1,ack(2,1))=ack(1,5)=7
ack(2,3)=ack(1,ack(2,2))=ack(1,7)=9
ack(2,4)=ack(1,ack(2,3))=ack(1,9)=11
ack(3,0)=ack(2,1)=5
ack(3,1)=ack(2,ack(3,0))=ack(2,5)=13
ack(3,2)=ack(2,ack(3,1))=ack(2,13)=29
ack(3,3)=ack(2,ack(3,2))=ack(2,29)=61
ack(3,4)=ack(2,ack(3,3))=ack(2,61)=125
上述過程,略去一些小細節,但讀者可以依照上述推導將該問題解決。
自下而上,對付遞歸的好辦法。
2.思考過程如圖所示:
答案:181 110 87 76 66 62 61 60
3.
根據該圖找規律:
根據該圖做計算:
答案:1348
4.
y1=1
y3=3
y2=4
y1=2
y3=5
y2=9
y1=3
y3=7
y2=16
y1=4
y3=9
y2=25
發現y2變化規律與第五屆(NOIP1999)第二大題很象。
爲了照顧之前學習的數學體系,令y1=n,y2=y(n)
y(1)=4
y(2)=y(1)+5=y(1)+2*2+1
y(3)=y(2)+7=y(2)+2*3+1
y(4)=y(3)+9=y(2)+2*4+1
……
y(n)=y(n-1)+2*n+1 :1
有了通式後,開始推導y(n):
y(n)=y(n-2)+2*(n-1)+1+2*n+1 :2
y(n)=y(n-3)+2*(n-2)+1+2*n+1 :3
y(n)=y(n-4)+2*(n-3)+1+2*n+1 :4
……
y(n)=y(1)+2*(1+1)+1+……+2*n+1 :
2*(1+1)+1+……+2*n+1個數爲x
n-x=1
x=n-1
等差數列
2*(1+1)+1+……+2*n+1=(2*(1+1)+1+2*n+1)*(n-1)/2
2*(1+1)+1+……+2*n+1=(n+3)(n-1)
y(n)=4+(n+3)(n-1)
輸入數據:
y(n)=23420
n^2+2*n-23419=0
n=(-2+sqrt(4+4*23419))/2;(負值已被捨去)
n=-1+2*sqrt(5855);
手工計算:
75^2=5625
76^2=5776
77^2=5929
76.5^2=5852.25
假定:
sqrt(5855)=76.55
n=76.55*2-1
n=152.1
取大於152.1的整數
n=153
即y1=153
答案:153
1難2中等3中等4難
2016-12-9 20:55