24授業班  

C言語卒業プロコン解説

1問目「果物 (Fruit)」

解説

\(x+y+3\)を出力するだけです。

解答例
#include<stdio.h>
int main(){
    int x,y;
    scanf("%d %d",&x,&y);
    printf("%d\n",x+y+3);
    return(0);
}

2問目「和の判定 (Sum Checker)」

解説

考えられるのは\(C=A+B , A=B+C , B=C+A\)の3通りなので、if文で処理ましょう。

解答例
#include<stdio.h>
int main(){
    int a,b,c;
    scanf("%d %d %d",&a,&b,&c);
    if(a==b+c||b==c+a||c==a+b){
        printf("1\n");
    }else{
        printf("0\n");
    }
    return(0);
}

3問目「ハミング距離 (Hamming Distance)」

解説

前から探索していき、違うところを数えるだけです。

解答例
#include<stdio.h>
int main(){
    int n,count = 0;
    scanf("%d",&n);
    char s[n+1],t[n+1];
    scanf("%s %s",s,t);
    for(int i = 0;i < n;i++){
        if(s[i] != t[i]){
            count++;
        }
    }
    printf("%d\n",count);
    return(0);
}

4問目「現れている数字 (Appearing Numbers)」

解説

すでに出たかを配列にいれておくことで簡単に実装できます。

解答例
#include<stdio.h>
int main(){
    int n,a[10];
    scanf("%d",&n);
    for(int i = 0;i < n;i++){
        int x;
        scanf("%d",&x);
        a[x] = 1;
    }
    for(int i = 0;i < 10;i++){
        if(a[i] == 1){
            printf("%d\n",i);
        }
    }
    return(0);
}    

5問目「変数の型」

解説

ただ、計算するだけですが、変数型に気を付けましょう。
※int型だとオーバフロー、float型だと有効桁数不足です。

解答例
#include<stdio.h>
int main(){
    long long a1,a2;
    double b1,b2;
    scanf("%lld %lld %lf %lf",&a1,&a2,&b1,&b2);
    printf("%lld\n%.10lf\n",a1*a2,b1/b2);
    return(0);
}

6問目「君の名は~下剋上~」

解説

if文で大文字なら小文字に、小文字なら大文字に変換しましょう。

解答例
#include<stdio.h>
int main(){
    char c[101];
    int i = 0;
    scanf("%s",c);
    while(c[i] != '\0'){
        if(c[i] <= 'Z'){
            c[i] += 'a'-'A';
        }else{
            c[i] -= 'a'-'A';
        }
        i++;
    }
    printf("%s\n",c);
    return(0);
}

7問目「highest」

解説

二次元配列の問題です。読み込んで最大値を出力するだけです。

解答例1
#include<stdio.h>
int main(){
    int h,w,x=0,y=0;
    scanf("%d %d",&h,&w);
    int a[h][w];
    for(int i = 0;i < h;i++){
        for(int j = 0;j < w;j++){
            scanf("%d",&a[i][j]);
        }
    }
    for(int i = 0;i < h;i++){
        for(int j = 0;j < w;j++){
            if(a[x][y] < a[i][j]){
                x = i,y = j;
            }
        }
    }
    //配列は0indexだが出力は1indexなので気を付ける。
    printf("%d %d\n",x+1,y+1);
    return(0);
}

下記のようなコードを書くことで問題の意図を無視できます。

解答例2
#include<stdio.h>
int main(){
    int h,w,x=0,y=0,z,Max = 0;
    scanf("%d %d",&h,&w);
    for(int i = 0;i < h;i++){
        for(int j = 0;j < w;j++){
            scanf("%d",&z);
            if(Max < z){
                x = i+1,y = j+1;
                Max = z;
            }
        }
    }
    printf("%d %d\n",x,y);
    return(0);
}    

8問目「背の順」

解説

ソートするだけです。解答例は直接選択法です。

解答例
#include<stdio.h>
int main(){
    int n;
    scanf("%d",&n);
    int a[n];
    for(int i = 0;i < n;i++){
        scanf("%d",&a[i]);
    }
    for(int i = 0;i < n;i++){
        int Max = i,tmp;
        for(int j = i+1;j < n;j++){
            if(a[Max] < a[j]){
                Max = j;
            }
        }
        tmp = a[Max];
        a[Max] = a[i];
        a[i] = tmp;
    }
    for(int i = 0;i < n;i++){
            printf("%d\n",a[i]);
    }
    return(0);
}

9問目「バイトテロユタカ2」

解説

単純にループを回すだけだとTLEしてしまいますが、累積和を用いることで高速化できます。

解答例
#include<stdio.h>
int main(){
    int n,q;
    scanf("%d %d",&n,&q);
    int a[n],b[n+1];
    b[0] = 0;
    for(int i = 0;i < n;i++){
        scanf("%d",&a[i]);
        b[i+1] = b[i]+a[i];
    }
    for(int i = 0;i < q;i++){
        int l,r;
        scanf("%d %d",&l,&r);
        printf("%d\n",b[r]-b[l-1]);
    }
    return(0);
}

10問目「大きな素数」

解説

\(X\)が素数かは
\(2\)以上\(\sqrt{X}\)以下のいずれかの数で
割り切れるかどうかで判定できます。\(1\)の時は注意しましょう。

解答例
#include<stdio.h>
int main(){
    int n;
    scanf("%d",&n);
    for(int i = 0;i < n;i++){
        int x,y = 0;
        scanf("%d",&x);
        for(int j = 2;j*j <= x;j++){
            if(x%j == 0){
                y = 1;
            }
        }
        if(y == 0&&x != 1){
            printf("Good\n");
        }else{
            printf("Bad\n");
        }
    }
    return(0);
}

11問目「Number-Collection」

ヒント

問題文より\(a_i \leq a_j(i < j)\)とあるので、
数列\(a\)は整列済みと分かります。
よって二分探索法を用いることができます。

解説

二分探索で\(X\)未満の個数と\(X\)以下の個数を求ます。
すると、「\(X\)以下の個数-\(X\)未満の個数=\(X\)の個数」
となり解を\(O(QlogN)\)で求めることができます。

解答例
#include<stdio.h>
int main(){
    int n;
    scanf("%d",&n);
    int a[n];
    for(int i = 0;i < n;i++){
        scanf("%d",&a[i]);
    }
    int q;
    scanf("%d",&q);
    for(int i = 0;i < q;i++){
        int x;
        scanf("%d",&x);
        int l = -1,r = n,k;
        //x未満の数を求める
        while(r-l > 1){
            int mid = (l+r)/2;
            if(a[mid] >= x){
                r = mid;
            }else{
                l = mid;
            }
        }
        k = r;
        l = -1,r = n;
        //x以下の数を求める
        while(r-l > 1){
            int mid = (l+r)/2;
            if(a[mid] > x){
                r = mid;
            }else{
                l = mid;
            }
        }
        //x以下の数-x未満の数=xの個数
        printf("%d\n",r-k);
    }
    return(0);
}