taiPyのお悩み解決ブログ

日々の発見をまとめます!

Javaの解答例:学習記録:A26 - Prime Check , 競技プログラミングの鉄則 演習問題集

はじめに

競技プログラミングの鉄則 演習問題集の「A26 - Prime Check 」という問題です!

今回のポイント

ポイントは素数かどうかを判定するときに、整数の性質を使うのがポイントです!素数とは1とその数以外の約数を持たない数の事でしたよね。逆に言えば、普通の約数を持つ場合は、素数ではないということ。

18が素数かどうかを判定したいとします。平方根を取ってあげるといい。素数じゃないときは、平方根以下の約数が絶対に存在するから。18の平方根は9。他の数でもやってみてください。素数と素数じゃないバージョン両方試すと分かりやすいかと。

目次

問題と解説へのリンク

問題

atcoder.jp

解説

github.com

解答例

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int q = sc.nextInt();
        int[] list = new int[q];

        for (int i = 0; i < q; i++) {
            list[i] = sc.nextInt();
        }

        for (int i = 0; i < q; i++) {
// 下記にisPrime() という関数を作成している
            if (isPrime(list[i])) {
                System.out.println("Yes");
            } else {
                System.out.println("No");
            }
        }
    }

    private static boolean isPrime (int x) {
// 2以上っていうのがみそ
// 平方根を i * i で表している
        for (int i = 2; i * i <= x; i++) {
            if (x % i == 0) {
                return false;   
            }
        }

        return true;
    }
}

Javaの解答例:学習記録:B - Minesweeper , AtCoder Beginner Contest 075

はじめに

作りかけです。2024年4月10日 21時10分。おやすみなさい。明日の自分よ、頑張れ!

今回のポイント

目次

問題と解説

問題

atcoder.jp

YouTube解説

www.youtube.com

解答例

import java.util.Scanner;

public class Main {
    static int H, W;
    static String[] B = new String[101];

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        H = scanner.nextInt();
        W = scanner.nextInt();
        for (int y = 0; y < H; y++) {
            B[y] = scanner.next();
        }

        for (int y = 0; y < H; y++) {
            for (int x = 0; x < W; x++) {
                if (B[y].charAt(x) == '.') {
                    int c = 0;
                    for (int dx = -1; dx <= 1; dx++) {
                        for (int dy = -1; dy <= 1; dy++) {
                            if (dx == 0 && dy == 0) continue;
                            int xx = x + dx;
                            int yy = y + dy;
                            if (0 <= xx && xx < W && 0 <= yy && yy < H) {
                                if (B[yy].charAt(xx) == '#') c++;
                            }
                        }
                    }
                    char[] temp = B[y].toCharArray();
                    temp[x] = (char) ('0' + c);
                    B[y] = new String(temp);
                }
            }
        }

        for (int y = 0; y < H; y++) {
            System.out.println(B[y]);
        }
    }
}

Javaの解答例:学習記録:B - Foreign Exchange , トヨタ自動車プログラミングコンテスト2024#2(AtCoder Beginner Contest 341)

はじめに

トヨタ自動車プログラミングコンテスト2024#2(AtCoder Beginner Contest 341)のB - Foreign Exchange という問題の学習記録です。Javaで書いています。

メモ

この問題のポイント

  • 例から考えること
  • 手を動かして考えること
  • Long型を使うこと。intで書いていた部分を全部longに変えるとAC(要するに正解)しました!

目次

問題と解説

問題

atcoder.jp

解説

www.youtube.com

YouTube解説

atcoder.jp

解答例

ステップ

  • インプットを格納する
  • 1つ目の国から取れるだけお金を交換する
  • これを最後までする。

はい、以上!

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();
        long[] a = new long[n];
        for (int i = 0; i < n; i++) {
            a[i] = sc.nextInt();
        }
        long[] s = new long[n - 1];
        long[] t = new long[n - 1];

        for (int i = 0; i < n - 1; i++) {
            s[i] = sc.nextInt();
            t[i] = sc.nextInt();
        }

        for (int i = 0; i < n - 1; i++) {
            long temp = a[i];
            // System.out.println(temp);

            long order = s[i];
            // System.out.println(order);
            
            long quotient = temp / order;

            a[i + 1] += quotient * t[i];
            // System.out.println(a[i + 1]);
        }

        System.out.println(a[n - 1]);

        sc.close();
    }
}

公式の回答をJavaに!

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        long n = scanner.nextLong();
        long[] a = new long[200001];
        long[] s = new long[200001];
        long[] t = new long[200001];

        for(int i = 1; i <= n; i++) a[i] = scanner.nextLong();
        for(int i = 1; i <= n-1; i++) {
            s[i] = scanner.nextLong();
            t[i] = scanner.nextLong();
        }

        for(int i = 1; i <= n-1; i++) a[i+1] += a[i]/s[i] * t[i];
        System.out.println(a[(int)n]);
    }
}

短く1行で収まりますね!

Javaの解答例:学習記録:C - One Time Swap , モノグサプログラミングコンテスト2024(AtCoder Beginner Contest 345)

はじめに

備忘録として。

この問題のポイント

あんまりよくわかっていないので、これはしっかりと理解したい!!

  • 考察をしっかりとすること!
  • 文字を入れ替えた時に①入れ替えようが入れ替えまいが同じ文字になること、②違う文字列ができること。
  • ②違う文字列ができる。でもかぶる文字列があるんじゃない?なら、単純にはできない。
  • 今回求めたいのはちょうど 1 回 ある場所の文字とある場所の文字を交換した後の文字列としてあり得るものがいくつあるか求めてください。要するに、あの操作したら、何通りくらい文字作れる?って感じ。
  • 例から問題の性質を考察する。考える!そういうテクニックが競プロでは有効!まあ、現実世界でも有効な気がします!

同じ文字になるを考察

  • 同じ文字になる。同じ文字を選ぶ選び方は何通りありますか?ということ。だから、

目次

問題と解説まとめ

問題 atcoder.jp

Javaの解答例

このコードをJavaへ変換しました!

提出コード Submission #51356715 - Monoxer Programming Contest 2024(AtCoder Beginner Contest 345)

解説YouTube www.youtube.com

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String s = scanner.next();
        int n = s.length();

        long same = 0;
        Map<Character, Integer> cnt = new HashMap<>();
        for (char c : s.toCharArray()) {
            cnt.put(c, cnt.getOrDefault(c, 0) + 1);
        }

        for (int m : cnt.values()) {
            same += c2(m);
        }

        long diff = c2(n) - same;

        long ans = diff;
        if (same > 0) ans++;

        System.out.println(ans);
    }

    private static long c2(long n) {
        return n * (n - 1) / 2;
    }
}

Javaの解答例:学習記録:C - Colorful Beans , トヨタ自動車プログラミングコンテスト2024#4(AtCoder Beginner Contest 348)

はじめに

この問題のポイント

  • 愚直にやると、メモリの制限と制限時間に間に合わなくなるかも。
  • 配列を用意する時にもメモリの要領を確保しないといけないからね。小さいなら問題ないけど、大きいならちょっと。キャリーケースに分厚いニットを入れるとほかの者がいれられないのに似ている。
  • だから、連想配列を使うよ。
  • 最小値の最大化は二分探索を使うらしい。
  • 解法が分かっていただけに悔しかった問題。でも実装できないんですよねー。
  • これをきっかけに連想配列の使い方をマスターしよう!

目次

問題と解説

問題 atcoder.jp

解説 atcoder.jp

YouTube youtu.be

解答例

公式の解答を私なりに、Javaに変換

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int[] a = new int[N];
        int[] c = new int[N];

        Map<Integer, Integer> mininumTaste = new HashMap<Integer, Integer>();


        for (int i = 0; i < N; i++) {
            a[i] = sc.nextInt();
            c[i] = sc.nextInt();
        }

        for (int i = 0; i < N; i++) {
            if (mininumTaste.containsKey(c[i])) {
                mininumTaste.put(c[i], Math.min(mininumTaste.get(c[i]), a[i]));
            } else {
                mininumTaste.put(c[i], a[i]);
            }
        }

        int ans = -1;
        for (int i : mininumTaste.keySet()) {
            ans = Math.max(ans, mininumTaste.get(i));
        }

        System.out.println(ans);

        sc.close();
    }
}

ほかの解答例

なるほど、解法の部分をsolve()としてmain()の外に出しているのですね。参考になります。

atcoder.jp

import java.util.*;
import java.io.*;

public class Main {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();

        int[] a = new int[n];
        int[] c = new int[n];
        for (int i = 0; i < n; i++) {
            a[i] = sc.nextInt();
            c[i] = sc.nextInt();
        }

        System.out.println(solve(n, a, c));
    }

    static String solve(int n, int[] a, int[] c) {
        HashMap<Integer, Integer> cmin = new HashMap<>();
        for(int i=0; i<n; i++) {
            cmin.put(c[i], Math.min(a[i], cmin.getOrDefault(c[i], Integer.MAX_VALUE)));
        }
        int result = 0;
        for(Integer ai: cmin.values()) {
            result = Math.max(result, ai);
        }

        return String.valueOf(result).trim();
    }
}

所感

ほかの人のコードを見るの面白いですね! なんか、こう、めちゃくちゃ長いのから、普通にきれいなものまでたくさんありますね。あと、テクニック満載なものもあって、見ていて面白い。

Javaの解答例:B - Farthest Point, トヨタ自動車プログラミングコンテスト2024#4(AtCoder Beginner Contest 348)

はじめに

自分用の備忘録。

メモ、ポイント

  • 問題文を読むこと。違う距離の出し方をしていて、それが要因で答えが違ったんですよね。
  • マイクロブレイク。詰まった時ほど休んでいこう。
  • 普通に、寝坊。30か40分遅れての参加で焦りが。。もう少し前に仮眠をとるか。

目次

問題と公式の解説

問題 atcoder.jp

解説 atcoder.jp

自作の解答例

コメントアウトしている、printはあれです。デバック用です。

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        // input
        int N = sc.nextInt();
        int[] X = new int[N];
        int[] Y = new int[N];
        for (int i = 0; i < N; i++) {
            X[i] = sc.nextInt();
            Y[i] = sc.nextInt();
        }
        // process

        for (int i = 0; i < N; i++) {
            // distance
            int ans = 0;
            int tempX = X[i];
            int tempY = Y[i];
            double tempDistance = 0;
            // max?
            for (int j = 0; j < N; j++) {
                // d = Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))
                double distance =  Math.sqrt((tempX - X[j]) * (tempX - X[j]) + (tempY - Y[j]) * (tempY - Y[j]));
                // int distance = Math.abs(tempX - X[j]) + Math.abs(tempY - Y[j]);
                // System.out.println("tempDistance" + tempDistance);
                // System.out.println("distance" + distance);
                // System.out.println(j);
                if (distance > tempDistance) {
                    tempDistance = distance;
                    ans = j + 1;
                }
            }
            // output
            System.out.println(ans);

        }
        
        sc.close();
    }
}

公式をJavaに変換

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int[] x = new int[n];
        int[] y = new int[n];
        for (int i = 0; i < n; ++i) {
            x[i] = scanner.nextInt();
            y[i] = scanner.nextInt();
        }

        for (int i = 0; i < n; ++i) {
            int max_dist = 0; //距離の2乗の最大値
            int idx = -1;     //距離が最大になる点の番号(0-indexed)
            for (int j = 0; j < n; ++j) {
                int dist = (x[i] - x[j]) * (x[i] - x[j]) +
                           (y[i] - y[j]) * (y[i] - y[j]); // 点i,jの距離の2乗
                if (max_dist < dist) {
                    // 距離の最大値が更新された場合
                    max_dist = dist;
                    idx = j;
                }
            }
            System.out.println(idx + 1);
        }
    }
}

参考文献

todo 必要あれば、追加。

Javaの解答例:学習記録:A37 - Travel 2 , 競技プログラミングの鉄則

はじめに

自分用の備忘録。

ポイント

部分に分解して、答えへの寄与度を求める。イメージは、モテる男性の特徴を知性、ユーモア、外見、年収に分解して、モテに対してどれくらいモテに重要なのかを求めるのと近いね。

問題

A37 - Travel 2 , https://atcoder.jp/contests/tessoku-book/tasks/tessoku_book_ak

ALGO 市には N 個の駅と M 個のバス停があり、下図のように道路で結ばれています。 すべての組 (i,j) に対して「駅 i からバス停 j までの所要時間」を足した値はいくつですか?

解答例

import java.util.*;

class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        // 入力
        int N = sc.nextInt();
        int M = sc.nextInt();
        long B = sc.nextLong();
        long[] A = new long[N + 1];
        long[] C = new long[M + 1];
        for (int i = 1; i <= N; i++) A[i] = sc.nextLong();
        for (int j = 1; j <= M; j++) C[j] = sc.nextLong();

        // 答えの計算
        long Answer = 0;
        for (int i = 1; i <= N; i++) Answer += A[i] * M;
        Answer += B * N * M;
        for (int j = 1; j <= M; j++) Answer += C[j] * N;

        // 出力
        System.out.println(Answer);
    }
};

自分が書いた間違えたコード

マジでどこが間違っているかわからん。将来の私よ、頼んだ。

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        // インプットを格納していきまーす。
        int N = sc.nextInt();
        int M = sc.nextInt();
        int B = sc.nextInt();

        int[] A = new int[N];
        int[] C = new int[M];

        // ここ少し忘れていて、ぜんぜん応え合わないじゃん、ってなって焦った。
        for (int i = 0; i < A.length; i++) {
            A[i] = sc.nextInt();
        }

        for (int i = 0; i < C.length; i++) {
            C[i] = sc.nextInt();
        }

        // トリマBの時間を求めるで。
        /* BはNとMの組み合わせ分あるから、次の式で求める。
         * 理由:どこから出発しようとも絶対に通るからね。
         */
        int BTime = B * N * M;

        // Aの時間、(図で言うなら左)の時間を求めるで。
        /* 左の時間全部足して、右の数かけてやる感じ。
         * 中学校で学んだ分配法則使うで。
         */
        int ATime = 0;
        for (int i = 0; i < N; i++) {
            ATime += A[i];
        }
        // System.out.println(ATime);
        // 上記のコメントは、「え?答え合わないじゃん、どこ間違ってるの?」って軽くデバックした時の名残
        ATime = ATime * M;

        int CTime = 0;
        for (int i = 0; i < M; i++) {
            CTime += C[i];
        }
        // System.out.println(CTime);
        // 上に同じ。
        CTime = CTime * N;

        // じゃあ、全部足して、出力するで。
        System.out.println(ATime + BTime + CTime);

        // ほな、さいなら
        sc.close();
    }
}

参考文献