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難

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章