【令和最新版】AtCoder 色変記事:茶色【Java】

Java で入茶したぞ!!!わーい

この度, AtCoder Beginner Contest (以下, ABC) 314 で無事に入茶しました. ですので忘れないうちに入茶記事を書いておこう, という感じのアレです. 駄文ではありますが最後まで読んでいただけますと嬉しいです. (というのは建前で実際は入茶前から少しずつこの記事を書いているので更新日とかがめちゃくちゃです. その辺細かいことは気にしないで☆)

スペック紹介

  • 情報系大学院修士 1 年 (専門は信号処理)
  • IT パスポート所持 (但し本物のパスポートは所持していないので海外旅行が出来ない)
  • 学部時代にアルゴリズムを落単 (必修)
  • 競技プログラミングはこれが初めて
  • プログラム自体はぼちぼち書いた経験あり
  • 数学は苦手ではない, 程度.

何で AtCoder を始めたの?

  1. もうすぐ就活か〜〜
  2. コーディングテストとか出されたら詰むなあ
  3. というか, そもそも論としてアルゴリズムなんも分からん
  4. 周りの強い人みんな AtCoder やってるし僕も始めるか〜
  5. ……楽しいな? これ

確かこんな感じでした. 記憶が曖昧なので嘘ついてたらすいません.

いつから初めていつ入茶?

最初のコンテスト参加は 2023/04/09 の ABC 297 でした. が, Rated とか Unrated とか良く分からずに参加したため Unrated. 悲しい. ちなみに順位は 3 完 (o3o—–) の 5581 位.

その後は, AtCoder やってた友人に細かいルールを聞いたので Rated 参加……のハズが DDoS 攻撃をドスドス (ここ笑うところ) されたのていたので結局 5 月に入るまで Unrated. この間は (AtCoder 社員さん頑張れ〜〜) などと AtCoder 社員さんの胃を心配しながら参加していました.

コンテストは基本 ABC のみの参加で, 気が向いたときは ARC に Rated 参加していました. が, 何も分からなかったので初心者の Rated 参加は ABC だけ良いんじゃないかな. ただ ARC の参加自体は良い刺激にはなります (何もわからんかったな〜勉強しないとな〜という感じのアレ).

使ってる言語は?

基本的に Java.

言語選定の理由

思想.

書いてる環境は?

自作テンプレをベースに回答を VSCode で書いて, コピペ提出をしています. C++ とかと比較すると多少遅いとは思いますが, 少なくとも入茶レベルでは一切気にならないので問題ないんじゃないかと思います. このレベルで TLE するときは普通にコードの書き方が悪いです, 上位は知らん. 一応使用している自作テンプレ (CC0) は最後に貼っておきますね.

あと gg ると sc.nextInt(); は遅いので, Integer.parseInt(sc.next()); を使うか自作 scanner を使おう! 的な記事が幾つか出てきますが, あれは強い人が更に強くなるための情報なので灰色レベルのプレイヤーは気にせず sc.nextInt(); と使えば良いと思います. 覚える情報は少ないほうがいいよ. ただ, 出力については System.out.println("hogehoge"); って書くのが面倒なので, PrintWriter をテンプレートに用意しておいて pw.println("hogehoge"); して flush(); するほうが良いと思います. ここのリンクが参考になるかも. これは純度 100% 個人の感想ですが, 灰色レベルでは高速化テクニック覚えるよりもアルゴリズムを覚える方に労力を割いたほうが良いと思います.

で, プログラムが完成したらテストケースをクリップボードにコピペして, ローカルで実行し結果を目視で確認しています. テストツールとか導入したいなあ (面倒なので放置中).

灰〜茶で使ったテクニック (?) とか Java の機能とか

  • DFS (何故だか分からんけど DFS が分かると簡単な問題が多い)
  • 累積和 (何故だか分からんけど累積和が分かると簡単な問題が多い)
  • String <-> char, int,… の変換
  • BigInteger, BigDecimal 等のクソデカ数
  • Arrays, List, Map, Set, Deque, stream 等の Java に搭載されてる便利機能

他にも色々使ってた気がしますけど, 特に印象に残ってるのはこの辺りです. まあ色々 gg りながら過去問を色々解いていればその内慣れます, 多分.

制限時間についてですが, A 問題, B 問題については気にせずに書いて大丈夫だと思います. 愚直書きましょう. C 問題から雲行きが怪しくなってくるので, C 問題に突入したら TLE にならないよう意識し始めるのが良いと思います. ループ回数については, けんちょんさんによると

1 秒間で処理できる for 文ループの回数は、 10^8 = 100000000 回程度

らしいです. 問題文と相談しながら考えてください.

トレーニング方法

AtCoder Problems を見つつ, 最新の問題から ABCABCABC…… の順でひたすら解いていました. 2023 年夏現在, 灰〜茶レベルでは (基本的にA~C問を解ける前提で) 回答時間がかなり順位に効いてくる印象なので「まあ解けるだろ」レベルの問題も飛ばさずに時間を意識しつつ解いてみると良いんじゃないでしょうか. あと僕は面倒なので基本バーチャル参加みたいなのはしていません, 書いて出すだけ.

あと本番には (可能な限り) 必ず出ましょう. 過去問で能力がついたとしても, 本番に出なければレートは上がりません. また AtCoder はリセマラ対策として, ある程度参加回数を重ねないとレートが低くなる傾向にあるらしいです. その意味でも沢山出ましょう.

あと分からない問題が出たときは鉄則本を辞書的に引いて読んでいます. この使い方が正しいかは分かりませんが, とても参考になるので非常に良い本だと思います (何様).

今後の目標

とりあえず緑目指して頑張ります. おわり.

自作テンプレート

適当に使ってください. 少なくとも現状においては Scanner の自作に代表されるような高速化処理は何もしていません. 理由は面倒だからです. ただし出力に関しては, 毎回 System.out.println("hogehoge"); と書くのが面倒なので pw.println("hogehoge"); で済むようにしています.

ざっくりとした使い方説明

基本的に回答は solve() メソッド上に記述します. main 関数内で Main インスタンスを作成しているので, メンバ変数, メソッドはグローバル変数っぽく使用できます. また先程も述べましたが, PrintWriter pw に表示したい要素を追加すれば最後に flush されるようになっています. その関係上, ARC-A で稀に良く出てくる対話的な問題は少し苦手です. いい感じに改良してあげてください.

solve() の頭で Boolean 型の変数が宣言されていると思います. これは回答が y/n で回答できるときに, bool 値を入れてあげると結果が出力されます. ただし, Yes / No としか出力できないので YES / NO みたいな問題には気をつけてください.

パッと思いついた注意事項はそれくらいですかね……多分.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/** atcoder template in Java @ CC0 */

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


public final class Main {
    private final Scanner sc;       // 入力はここから拾う
    private final PrintWriter pw;   // 出力はここに流す
    // グローバル変数ここから
    
    // グローバル変数ここまで

    /**
     * 問題の計算を行うメソッド
     * @return status 回答のステータス
     *      true            : 回答が Yes のとき (出力が文字列 "Yes" でない可能性に注意 ex:"YES")
     *      false           : 回答が No のとき  (出力が文字列 "No"  でない可能性に注意 ex:"NO")
     *      null (default)  : 回答が Yes/No 形式ではないとき
     */
    private final Boolean solve() {
        Boolean status = null;

        // ここに回答を記述
        int n = sc.nextInt();
        pw.println(n);
        // 回答ここまで

        return status;
    }


    /**
     * テンプレート編集のとき以外は触る必要のない main 関数
     * @param args おそらく使わないであろうコマンドライン引数
     */
    public static void main(String[] args) {
        try ( // 入力元と出力先を設定
            final var sc = new Scanner(System.in);
            final var pw = new PrintWriter(System.out);
        ) {
            // 計算して
            final Boolean status = new Main(sc, pw).solve();
            // 判定して
            if(status != null) {
                if (status) {
                    pw.println("Yes");
                    // pw.println("YES");
                } else {
                    pw.println("No");
                    // pw.println("NO");
                }
            } else /* status == null */ {
                // Nothing to do.
            }
            pw.flush(); // 出力する
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }


    /** Main クラスのコンストラクタ. 入出力のやり取りくらい. */
    public Main(final Scanner sc, final PrintWriter pw) {
        this.sc = sc;
        this.pw = pw;
    }
}
Licensed under CC BY-SA 4.0 @ Fumiyoshi MATANO
Built with Hugo
テーマ StackJimmy によって設計されています。