AtCoder Beginner Contest 234(Rated範囲外)

コンテスト前のレート:2024
(Ratedだとしたら)レート通りのパフォーマンスが得られる順位:329位(2000点、47分33秒)

A - Weird Function

問題

思考過程
  1. 同じ計算を何度も実装するにはf(x)が複雑すぎるので、素直に関数fをメソッド化する。
  2. あとは問題文2行目の通り。
import java.util.Scanner;

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

        int ans = f(f(f(t) + t) + f(f(t)));
        System.out.println(ans);
    }

    static int f(int x) {
        return x * x + 2 * x + 3;
    }
}

ここまで1分53秒+0ペナ。901位。


B - Longest Segment

問題

思考過程
  1. _NC_2通りの全組合せについて、2点間の距離をhypotで計算し、その中の最大値を求める。
import java.util.Scanner;

public class Main {
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
        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();
        }
        sc.close();

        double ans = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < i; j++) {
                ans = Math.max(ans, Math.hypot(x[i] - x[j], y[i] - y[j]));
            }
        }
        System.out.println(ans);
    }
}

ここまで3分03秒+0ペナ。140位。


C - Happy New Year!

問題

思考過程
  1. 例2を見て11番目までを実際に手動で列挙してみると、2進数表現にして"1"を"2"に変えたものになっている。
import java.util.Scanner;

public class Main {
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
        long k = sc.nextLong();
        sc.close();

        StringBuilder sb = new StringBuilder();
        while (k > 0) {
            if (k % 2 == 1) {
                sb.append(2);
            } else {
                sb.append(0);
            }
            k /= 2;
        }
        sb.reverse();
        System.out.println(sb.toString());
    }
}

なお、2進数変換をわざわざ自力実装してしまったが、以下のようにして楽ができた。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
        long k = sc.nextLong();
        sc.close();

        System.out.println(Long.toBinaryString(k).replace('1', '2'));
    }
}

ここまで6分33秒+0ペナ。328位。


D - Prefix K-th Max

問題

思考過程
  1. Pを前から見ていって、常に大きい方からK個までを保持するようにTreeSetもしくはPriorityQueueで管理する。
  2. そのためには、K+1個目を追加したら最小値を削除する、ということを繰り返す。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.TreeSet;

public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] sa = br.readLine().split(" ");
        int n = Integer.parseInt(sa[0]);
        int k = Integer.parseInt(sa[1]);
        sa = br.readLine().split(" ");
        int[] p = new int[n];
        for (int i = 0; i < n; i++) {
            p[i] = Integer.parseInt(sa[i]);
        }
        br.close();

        TreeSet<Integer> set = new TreeSet<>();
        for (int i = 0; i < k - 1; i++) {
            set.add(p[i]);
        }

        PrintWriter pw = new PrintWriter(System.out);
        for (int i = k - 1; i < n; i++) {
            set.add(p[i]);
            if (i >= k) {
                set.pollFirst();
            }
            pw.println(set.first());
        }
        pw.flush();
    }
}

ここまで10分18秒+0ペナ。160位。


E - Arithmetic Number

問題
例3を見て、11桁以上は不可能では?と数分悩んでしまったが、全桁同じ値の場合に条件を満たす。

思考過程
  1. Xが途中まで等差数になっている場合、後ろの方の桁だけ書き換えるようにすればX以上で最小というのが満たせそうな気がする。
  2. Xの先頭i文字を取った部分文字列Yについて、下記を満たすかどうかを、iが長い順に調べてみる。
    • Yが等差数になっていて、かつXと同じ文字数まで伸ばした時に途中で0未満や10以上の桁が現れないか。
    • 差が負の場合は書き換えることによって小さくなることもあるので、最終的に作れた値がX以上か。
       
  3. X1桁だと差を取ることができず不都合なので最初に除いておく。
  4. 2桁の場合もX自身が答えになるので、ついでに除いておく。
     
  5. Y3桁以上の場合は差を保って伸ばすしかないが、2桁の場合はそもそも2桁目から変える余地がある。
  6. 元の2桁目の値~'9'を調べれば十分だが、'0'~'9'を全部調べても問題はない。
     
  7. これだけだとまだ例3が駄目で、元の1桁目を+1して2桁目'0'~'9'も調べる必要がある。

後から思えば結局1桁目と2桁目の組合せを9 \times 10通り試すだけだった。

import java.util.Scanner;

public class Main {
	static int n;
	static long lx;

	public static void main(String[] args) throws Exception {
		Scanner sc = new Scanner(System.in);
		String x = sc.next();
		sc.close();

		n = x.length();
		// 3, 4
		if (n < 3) {
			System.out.println(x);
			return;
		}
		lx = Long.parseLong(x);

		// 2 ここはいらなかった
//		for (int i = n; i > 1; i--) {
//			char[] y = x.substring(0, i).toCharArray();
//			if (exec(y)) {
//				return;
//			}
//		}

		char[] y = new char[2];
		// 5, 6
		y[0] = x.charAt(0);
		for (char i = '0'; i <= '9'; i++) {
			y[1] = i;
			if (exec(y)) {
				return;
			}
		}
		// 7
		y[0]++;
		for (char i = '0'; i <= '9'; i++) {
			y[1] = i;
			if (exec(y)) {
				return;
			}
		}
	}

	// 思考過程2の判定部分
	static boolean exec(char[] y) {
		int d = y[1] - y[0];
		for (int j = 1; j < y.length; j++) {
			if (y[j] - y[j - 1] != d) {
				return false;
			}
		}

		StringBuilder sb = new StringBuilder(String.valueOf(y));
		while (sb.length() < n) {
			int nx = sb.charAt(sb.length() - 1) - '0' + d;
			if (nx < 0 || 9 < nx) {
				return false;
			}
			sb.append(nx);
		}

		long ans = Long.parseLong(sb.toString());
		if (ans >= lx) {
			System.out.println(ans);
			return true;
		}
		return false;
	}
}

ここまで30分19秒+0ペナ。500位。



残りの3問は解けず。
Fが30分経っても解けなかった後は、3問並行して考えていた。
Fを解いても順位の上昇があまり見込めなくなってきてからは、後ろの2問により注力して考えていたが、どちらも2乗から落とす方法が全くわからず。



終結果:ABCDEの5完1500点、30分19秒、908位、パフォーマンス1521相当
レート変動:2024(Unrated)


新年早々PASTバチャ76点で上級にも届かず凹んでいたが、ABCでも相変わらず800~900位台を連発しているし、ちょっと下振れすれば普通にこの程度の実力しかないのかもしれない。

今年の目標はとりあえず黄色維持かなというところ。