NOIP 提高组 初赛 四、阅读程序写结果 习题集(三)NOIP2002-NOIP2003

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难




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值