MMA Contest 016オンサイト 参加記

これは2023年8月12日に行われたMMA Contest 016オンサイトの参加記。移動成分多め

準備

前提として、自分はノートPCを所持していない。オンサイトコンテストには自分のノートPCを持っていく人が殆どだと思うが、それが無いので早速困った。

最近はGitHub Codespacesという、WebブラウザからVSCodeを使ってクラウド上にあるLinux環境を触れるというものがあり、試しにPCから使ってみると、思いの外便利で良かった。

iPadにキーボードとマウスを合わせたら、これでオンサイト行けるぞ!となり、思い切ってiPad用のMagic Keyboardを購入して環境を整えた。

移動(行き)

会場の電気通信大学は東京にあり、自分の居住地からはいささか離れているものの、時間だけで言うと3時間ちょっとで思ったほどかからないな…という感じ。

久しぶりの京都駅。こからどこへでも行けそうな気がする。

お盆の時期なのもあり、ほぼ5分毎にのぞみ号が来ていてびっくりした。これがSuper Expressか...。間違った列車に乗りそうになったり、座席を間違えたりと出だしから躓く形に。列車を間違えたときは、パッセンジャーの人に指摘されて気がつくことができた。圧倒的感謝…

乗ったのはJR西日本の編成。AMBITIOUS JAPAN!から変わった新しいチャイムは聞けず。いい日旅立ち

新幹線のWi-Fi接続に苦戦した。iPhoneiPadの接続に成功した時列車は愛知県に入っていた。接続が難しいのか新幹線が早いのか...。

東京駅でドアが開くと、想像とは異なる涼しい空気が流れ込んできた。海パワー?

東京駅で中央線に乗り換えて新宿駅へ向かう。東京の列車はさぞかし早いのだろう(?)と謎の期待を抱きながら中央線に乗車したが、思ったほど早くなかった(それはそう)。一方、新宿駅から乗った京王線は地下や住宅地の中を通っているそうで、家々の間をものすごい勢いで走るので勝手にヒヤヒヤしていた。そして安い

調布駅からしばらく歩くと、「社会と調和の取れた実践的な教育・研究 電気通信大学」の看板と、compassで見たMMA Contestのロゴのようなものを持った人が立っているのが見えた。この道で合っているらしい。大学までの道は暑くてやーんという感じだったのだけど、大学構内に入ると涼しくなってびっくりした。やっぱ木があると違うのかしら。

会場内は飲食禁止という話を聞いていたので、今のうちに昼食(セブンイレブンで買ったおにぎり)を摂ることに。会場の建物の入り口の前でむしゃむしゃ食べていると、参加者と思われる人たちがちょいちょい中に入っていく。参加者は結構多いように見える。

会場

腹ごしらえが済み、会場に入ると結構な人数の参加者がいてびっくりした。

席は自由席。会場が一階二階で分割されているらしく、1階の会場に行くようにと指示された。壁側の席を確保してiPadの電源を用意したりと準備する。PCなどがたくさん設置されている部屋なのだが、キーボードのWindowsキーに相当するキーに印字されているマークが見たことのないもので気になったりしていた。kotatsugameさんの動画で見たことあるが、あれがHHKBというやつかしら?

コンテストが始まるまで30分ほどあり、暇になったので会場の建物の中をうろつくことにした。端末をロックしないで離席すると、勝手に「熟女好き」とツイートされてしまうと聞いたので、離席時のこまめなロックを欠かさない。

まずは入り口の方に行ってみると、建物内でセミが何かしらかに惨殺されたであろう現場を見つけた。羽の破片が散らばっている。その近くには何かしらかの死骸があった。生き物〜

一階と比べて二階の会場は賑やかだった。しかしコミュ力が無いので1分も保たず撤退する。

1階の会場の隣の部屋で誰かがくつろいでいた。謎の存在

コンテスト

開始直前まで参加者の間でわいわいがやがや交流が行われていたが、コンテストが始まると会場内は一気に静かになり、キーボードを打つ音だけになった。すげ〜という気持ちになりつつ、問題を開く。

https://yukicoder.me/contests/450

A問題 2 KA 3 KA

https://yukicoder.me/problems/no/2414

実際に体積と表面積を計算して判定する。

(後で見たらリジャッジでWAになっている。あろうことか、表面積を計算する式が間違っていた...。)

https://yukicoder.me/submissions/901453

B問題 偶数判定!Nafmoくん

https://yukicoder.me/problems/no/2415

$A \times B$を計算して偶奇を判定する。Pythonで書いたので、オーバーフローを気にせずできた。

入力の形式を間違えて1WA。もちつけ

本番では見落としていたが、入力が二進数で与えられる(!)ので、1桁目だけ見て判定するとらくちん。

https://yukicoder.me/submissions/901702

C問題 vs Slime

https://yukicoder.me/problems/no/2416

AB問題と比べてちょっと難しくなってきた。スライムを倒すまでの流れを書き出すと、問題文の内容のイメージがついた。

hが0になるまでAで何回割れるかを計算して($cnt = \lceil \log_h A \rceil$)、$2^{0} + 2^{1} + \dots + 2^{cnt-1} = 2^{cnt} - 1$を出力する。

浮動小数点数の誤差が怖かったので、cnt = ceil(log(h, A))とせず実際にAで割ってcntを計算したけど、後から試したらceil(log(h, A))でもACできたわね…。

https://yukicoder.me/submissions/901764

D問題 Div Count

https://yukicoder.me/problems/no/2417

正の整数$N$と非負整数$K$が与えられます。$N$を$A$で割った余りが$K$となるような正の整数$A$の個数を求めてください。

ひょえ!?問題文は簡潔だけど、いまいち解法が思いつかない。とりあえずサンプルを見て考えてみると、$N$を$N-K$で割ったあまりは$K$なことに気がついた(ここで落とし穴にはまってる)。では他にあまりが$K$になる数はというと、$N-K$の約数だ!となり、約数を列挙して、その個数を数えるコードを書いた。$K=0$の時にしか1は使えないのに注意しつつ、実装するもWAだった。え〜

提出結果を見てみると、なんとサンプルを含む全部のテストケースがWAになっている。なんだこれは!コードを読み返してみると、「$K \ne 0$の時、約数の個数から1を引く」という処理が、「$K=0$の時、約数の個数から1を引く」になっていた。うーん凡ミス。修正して再び提出すると、ACのケースがいくつかは出たがWA。

適当な数を入力したりして調べてみるうちに、$K$以下の約数ではあまりが変わってしまうことに気がついた。それはそう。$K$以下の約数を弾いて数えるよう変更して再び提出すると、ACできた。

https://yukicoder.me/submissions/902304

E問題 情報通だよ!Nafmoくん

https://yukicoder.me/problems/no/2418

うーん難しそう…と思いながら問題文を読んでいたけど、一番最後の、「知り合いの知り合いは知り合い」という部分で「連結成分だ!!!」となった。

連結成分の大きさを得るのは、BFSが一番素直だが、楽したいのでUnionFindをぺたり。(連結成分の大きさを2で割ったあまりの合計) // 2を出力してAC。あまりの合計が偶数になるか若干不安になったが、N組のペアが必ず作られるという制約を読み納得(?)して提出した。

https://yukicoder.me/submissions/902082

F問題 MMA文字列2

https://yukicoder.me/problems/no/2419

こういうコンテストの名前とかを問題に取り込んでくるの好き。

なんかこういう感じの問題をDPで解くのを見たことがある気がする!!と思ったけど、どうもDPで解く感じでもない気がしてきた。

すぐに思ったのは、1文字目2文字目として文字Aを使う時、個数は同じ文字Aを選ぶ組み合わせの数 * 二つ目の文字以降にあるA以外の文字の個数だなあ〜という気持ち。とはいえ、全部の組み合わせに対してそのような処理をしていては間に合わない。どうしたもんかいの〜〜と天井を見る。

天井を眺めているうちに、文字種ごとに出現回数をカウントしたらいい感じにならね?となり、文字の出現回数がわかる累積和を書いた。最初はなぜか反対側からカウントしようとしていたけど、その必要はない。

どうやってMMA文字列を作る方法を数えるかを考える。実験の過程でPythonの標準ライブラリにある組み合わせを計算する関数、math.combがそんなに遅くないことがわかったので、「comb(i文字目までにある文字Aの個数, 2) - comb(i-1文字目までにある文字Aの個数, 2)」に、前述の累積和で求めた「i文字目以降の文字A以外の文字の個数」をかけたらいい感じにならんか?となり、実装したらいい感じだったので提出し、AC。

最初に普通のPython(CPython)で提出したらTLEしたが、PyPyで再提出すると間に合った。

後から考えてみると、combなんか持ち出さなくてももっと簡単に解けたんだよな...。

https://yukicoder.me/submissions/902719

G問題 Simple Problem

https://yukicoder.me/problems/no/2420

$\sqrt A + \sqrt B < X$を満たす最小の整数Xを求めてください。

Simpleだあ…。Sqrt Inequalityのトラウマが蘇り、とりあえず式変形だ!となる。Sqrt Inequalityの解説を思い出しながら式変形すると、どうもそれっぽい式ができた。あとは二分探索で解けそう。

二分探索を実装したコードを提出してみたものの、TLEしてしまった。うーん…。式を眺めていると、再びSqrt Inequalityの記憶が。両辺を2乗する時、値が負になっていないかも判定しないといけないのだった。これを追加して再び提出するも、またもTLEしてしまった。

判定関数はちゃんとできているので、二分探索の範囲を小さくしようという気持ち。$1 \le A, B \le 10^{9}$なので、とりあえず$\sqrt{10^{9}} + \sqrt{10^{9}}$を計算してみると、およそ63245ということがわかった。これを踏まえて二分探索の上限を適当に100000に設定して再度提出するとACできた。

https://yukicoder.me/submissions/902575

H問題 entersys?

解けず。とっかかりの見えないままコンテストが終わった。

https://yukicoder.me/problems/no/2421

コンテスト終了後

作問者による解説が終わると、分の席から出入り口までの道の間に人だかりができて出れなくなってしまった。どうしたもんかいの~と思っていると、自分の後ろの席だったけんちょんさんの周りでブロックスの試合が始まったので観戦した。

1時間ほどでブロックスの試合が終わり、大変腹が減ったので会場を後にした。

移動(帰り)

駅まで歩こうと思っていたけど、途中でバス停を発見。眠かったので調布駅までバスに乗ることにした。前側のドアから乗車し、運賃は前払いで降車するドアは自由(終点なので?)と、普段自分が乗っているバスとは全部違って困惑した。特に料金については、てっきり後払いだと思っていたので不安になり乗務員に「本当にこのまま降りてもよいのか?」と尋ねてしまった。

新宿駅からSuicaのペンギン広場に行こうと思っていたけど、思ったより遠かったので断念。夕食の時間が危うい。

東京駅に着いた時点で帰りの新幹線が発車するまで30分。ここでラーメンを食べようと思っていたが、全ての店に行列ができており、およそ30分では下らないという感じ。

空腹で2時間半新幹線に乗るのはなんとしてでも避けたいので、何か食べ物にありつけないかと駅をうろうろし、最終的に八重洲口の"おむすび処 こめいん"でおむすびを二つ購入。八重洲口付近の外でむしゃむしゃ食べた。東京に来ておにぎりしか食べてないな…。レシートを見ると、「JR東海パッセンジャーズ」と書いてあった。また会いましたね…。

発車まで残り10分となり、改札を通ってホームに上がってみるも、列車がいない。発車標を見ても乗る予定の列車が無い。どうやら上がるホームを間違えたらしい。急いで正しいホームに向かい、無事列車に乗ることができた。

発車してしばらく経ち、静岡県に入ったところでABCに参加する。慣れない環境にしては良い感じの成績で満足。Rated参加にしても良かったわね。

帰りはJR東海の編成だったので、新しい車内チャイムの「会いにいこう」を聴くことができた。よき。行きであんなに苦戦したWi-Fi接続だが、帰りはすんなりと接続できた。JR西日本JR東海でシステムが違ったりする?

ABCの感想戦を眺めたりしているうちに京都駅に到着し、帰宅。つかれた~~

おわり

今回オンサイトのコンテストに参加するのは初めてで、どんなものかと不安な部分もあったが、とても楽しく参加できて非常に良かった。何より、自分以外の競プロerを初めて肉眼で観測できたのはとても嬉しいことだった。

リアルの交友関係に競プロをやっている人が1人もおらず、自分以外は全員botなんじゃないか?と思うこともあったが、そうではないということがわかった。

そして、開催に係った全ての人に感謝!!

関西にもこういうのないかな〜

リンク集

MMA Contestのcompassページ

MMA Contest 016(yukicoder)

youtu.be