むかでのチラ裏

競技プログラミング現役引退でチラ裏に・・・

週記(2021/07/05-2021/07/11)

07/05 (MON)

9:30 起床。鬼のように身体が重い。おそらく副反応の最後っ屁だろう。 昨日は $ 38.4 $ 度もあったのに全然元気だったのが嘘のように怠いし、頭痛もした。 先日に「 $ 38.4 $ 度あるけど元気だぜ」みたいなツイートをしてしまった手前 Twitter で体調不良ポストをするのが躊躇われた。 情けないぜ助けてくれ。

布団から出られる気がしないし、スマホで典型を確認する気にもならない。 $ 30 $ 分ぐらいゴロゴロした後、今日がゼミであることを思い出す。 流石に出られない可能性が高そうなので、欠席の旨を連絡しておいた。

メール送信ついでに BOX を確認すると、返信の必要な大事なメールが来ていたため対応する。 それだけしたら、食欲もないのでまたベッドに逆戻りした。

12:30 ぐらいになんか回復してくる。頭痛も和らいだし腹も減ったので、街に繰り出して昼食を探す。 昼食探しが下手すぎて、マクドナルドに行きついてしまう。 せっかく元気になってきたのでモバイルオーダーで迅速に注文してなんとか 13:00 のゼミに間に合うようにしたいというねらいもあった。

マックに到着するともう品物が用意されていた。目視できる距離で作り始めてもらったのに速すぎないか?すごい。

受け取るときにアンケートに答えてほしいみたいなことを店員に言われた。 滅茶苦茶早く購入が済んだのでクーポンももらえると言うので答えることにした。 訪問した店舗では、テストで「キオスク」なる端末を置いているらしくて、一般的な質問に加えてそれについての質問があった。

f:id:spider_0859:20210707192851p:plain:w400
キオスク。画像は拾い物でアメリカの写真らしい。

どうやらこの「キオスク」、海外ではもうすでに導入されており日本でのテスト導入が始まったとか。 機能は割と見たまんまで、この端末をタッチして注文をすることができる。 まあ言ってしまえばちょっと機能の多いセルフレジである。

ちなみに余談だが、自分が購入したのは当然のように、トリプルチーズバーガーである。 チー牛の匠なのでこのバーガーの復活期間にこれ以外注文するつもりは毛頭ない。

ちょっと失礼なのだが、ゼミを聞きながらマックを食べた。発表練習回なのと欠席連絡をしたので許してほしい。 あと今の体調だとナゲットが余計だったので頼んで後悔した。

ゼミが終了する。先週分の週記を投稿し忘れていたことに気が付いたので、投稿する。 そのあと Twitter を見たり、先日の ABC をちょっと真剣に振り返ってみたりした。 精進を真剣にするような体力がないので、ダラダラしていた。

20:00 から友人と用事(オンライン)の約束をしていたが、一時間伸びたので夕食までは本当にグダグダしていた。 今日に関しては本当に体調が悪くてだらだらしていたのでしょうがない。

夕食を食べて 21:00 から zoom に繋いで話す。

それすら終わると本当にやることがない。正しくはあるけど、今の元気さで出来ることがなくなる。 仕方がないので(?)追加されたというボルテの 19 の譜面でも見ることにした。

www.youtube.com

簡単と TL で言われている割には難しく見えた。 とはいえ、$ 2 $ 回目再生するとやっぱり PUC できそうな気もしてきたのでやらないとわからないかも。

そんなことでベッドに向かうのだが、本日は根つきが今年一番悪く最悪の夜だった。 明日は 9:30 - 18:30 勤務の something(詳しくは言わないでおくがインターンではない)の初日なのでマジで心配になった。

07/06 (TUE)

8:30 起床。全然眠れなかった。ゲボほど眠い。というかゲボ。 流石にやばいと思って $ 30 $ 分追加で寝る。 起きる。まだゲボほど眠い。助けてほしい。

とりあえず朝食を食べる。9:30 を迎えたので、作業に着手する。 進捗がゴミというか、$ 1 $ ㌨㍍も集中できなかったので昼休みの時間を前倒しで使用して仮眠をすることに決定。

なんとか起きていられるようになったので、作業をする。とてもつらい。 先程の時間の代わりに昼ごはんはマッハで食べる必要がある。あまり覚えていない。

そんなこんなで 18:30 までやった。正しくはボケてて 19:00 ぐらいまでやった気がする。 30 分で何かを生み出せたわけでもないので、どうでもいいが。

散々な日だった。 Twitter を見ると sak さんが以下のような自作問題ツイートをしていた。

ふむふむ。中央値の定義次第で細かいところは変わるだろうが、なんにせよ二項係数の積の和を求めれば良さそうだ。これをすれば前計算で階乗とその逆元(素数 $ \bmod $ の世界で答えることを想定している)を求めてしまえば、全体 $ O(N) $ で求まりそうだ。

因みに、二項係数の積の和という形は結構非自明に $ 1 $ つの二項係数に落ちがちな気がする。理由がわからないので適当を言っている。D - Binomial Coefficient is Fun とかまさにその波動を感じる。 頭がよくないのでこういうのを見たらとりあえず Wolfram|Alpha: Computational Intelligence に投げることにしている。今回のもちゃんと $ 1 $ の二項係数になったのでめでたしめでたし。

一応意味を考えてみると、グリッドの最短経路数問題で二項係数を考えると、二項係数の掛け算はある中継地点を通る時の経路数になりそうだ。とすると、式をよく見ると単一始点単一終点の最短経路数問題の答えと和が一致することが確認できる。

この形の二項係数の変形って式から行くより意味を考えた方が却って分かり易いことが多いと思う。

その後、Streak のために C - 蛍光灯 を開く。

問題概要。$ L $ メートルの廊下があって、$ N $ 個のライトで廊下を全て照らしたい。$ i $ 番目のライトは左から $ l_i $ から $ r_i $ メートルまでを照らせて $ c_i $ だけ使うのにコストがかかる。最小のコストで廊下全てを照らせ、という問題。

見た瞬間困惑した。これ自分が初めてからの ARC 級のコンテストで全く同じの出題されたぞ。解法は簡単で $ r_i $ でソートして左から照らしていくことを考える。$ [l_i, r_i) $ まで照らせたときの最小コスト + $ c_i $ で $ r_i $ まで照らせた時の最小コストを更新するような DP をすれば $ O(L \log L) $ で解ける。 ちなみに全く同じ問題というのはこれ→D - Shortest Path on a Line

明日も 9:30 - 18:30 なので就寝。

07/07 (WED)

8:30 起床。生活リズム自体は勤務によって正されていていいかも。 今日は死ぬほど眠くはない。助かった…

朝食を食べてから 9:30 に作業を開始する。 12:30 から昼休憩に入る。進捗は正直微妙だが、昨日に比べれば…

今日はピアノの稽古があるので途中の非勤務時間を通常の $ 1 $ 時間から $ 3 $ 時間にした。 母親が昼食を用意してくれていた。ソース焼きそばがメインで他は残り物だ。美味しかった。

さて、稽古までの時間はウォーミングアップが必要なので練習をしていた。

ついに目的地の目前で大ゴケしてしまった。 その際に左手首を負傷した。

週記(2021/06/28-2021/07/04) - むかでの競プロ備忘録

正直この一週間は先週のこれのせいで左手首を少し捻ると痛いので練習ができなかった。 $ 1 $ 時間程度で何ができるのかと泣きながら練習をしたが、$ 2 $ 時間分ぐらいはうまくなったかも。

帰ってきて、ちょうど $ 3 $ 時間なのを確認して作業に戻る。 読んでいる論文の $ 1 $ つが面白くて賢く、非常に良かった。

さて、18:30 になって一息つく。 具体的にはインストールしている漫画アプリの動画広告を再生しまくって無料ポイントをむさぼる時間にしていた。 複数の漫画アプリを入れて毎日動画を再生しまくると結構馬鹿にならない量のポイントがゲットできる。

夕食前に、今週の週記は開始が副反応で全然書けていなかったため、Google Chrome の履歴を開きながらその日あったことを思い出しながら書いた。 基本的に TwitterChrome を開いているため、両方を確認すれば自分がその日何を考えて何をしていたかが大体わかる(危険だろ)。

夕食中と食後、母親が佐々木蔵之介主演の「サイバー捜査班」みたいなドラマを見ていたので一緒に見る。 ツッコミどころがないわけではないが、そこはフィクションなので粗さがしをするのは野暮というものだろう。 とはいえ、こういうのはあまりにもお粗末だと興ざめしてしまうのだが、ストレスは特になく受け入れられるものだった。 強いて言えば主人公の一人の女性刑事がちょっと邪魔をしてきて鬱陶しい場面が少しあったぐらいか。

そういえば、今日は Codeforces のコンテストがあった気がする。 その前に Streak をつないでおかねば。今週が典型 90 の最終週なのでそちらも処理したいが Streak はモチベの一つなので切るわけにはいかない。

Streak をつないだところで、Dashboard - Codeforces Round #730 (Div. 2) - Codeforces をやる。

A 問題。$ 2 $ つの正整数があって、両方に対して $ +1, -1 $ する操作が任意回数できて、$ \gcd $ を出来るだけ大きくする問題。 差が一定が自明で、$ \gcd $ は差の約数であることが有名なので差になるようにする。

B 問題。長さ $ N $ の数列 $ A $ が与えられて、総和が変わらないように再分配し、$ \sum _ i \sum _ j | A_i - A_j | \quad (i<j) $ が最小になるようにして最小値を求める。 均等に配るのが最適と簡単に証明できる。最後の一周配られる数を $ x $ とすると答えは $ x (N - x) $。

D 問題。部分点がある。$ a \oplus _ k b $ を $k$-itwise XOR ということにして、これは $ k $ 進数にして各桁ごとに $ \pmod k $ の和を取るという演算と定義される。$ 0 $ から $ N-1 $ のパスワードを $ N $ 回使って当てるというインタラクティブ問題なのだが、$ 1 $ 回外すと、元のパスワードを $ x $ 、間違ったパスワードを $ y $ として $ x \oplus _ k z = y $ のような $ z $ に変更されてしまう。

D1 は $ k=2 $ で固定。これにより $ \oplus _ k $ は $ \oplus $ になって、$ z = x \oplus y $ 今までの $ y $ の累積 xor を持っていれば元々のパスワードが $ 0,1,2, \cdots $ の順に検査できる。

D2 も基本方針は同じ。ただ $ k=2 $ の時と違ってしっかり符号を考えなくてはならない。$ z = y \ominus _ k x $ のように書ける。元々の演算が各桁の和なので逆も簡単に定義できる。計算量を小さくするために $ y $ の方を累積させていきたいが、結構符号合わせが面倒でしばらく地蔵になっていた。

C 問題。解けね~。参っていた。しかし TL を見ると自分がボツにした「 $ p $ 以外の確率の状態を持てば十分で、$ Invalid $ が出るまでは $ \frac{v}{2} $ 刻みだし状態数は見た目より制限される」という解法がはびこっている。は~これは $ v $ がちっちゃかった時に結局状態数 $ 10^{8} $ ぐらいは余裕で行きそうだなと思ってあきらめたのだが、よく問題文を見直すと $ 0.1 \leq v \leq 0.9 $ と書いてある。ゴミ~~~。 これだから俺は同じ単位・次元の数値で、$ 1 $ つだけしれっと入力制約のところで弱い制約になっているのを許せないんだよね。 せめて太字にしませんか?

明日も勤務なのでシステス待たずに就寝。

07/08 (THU)

9:00 起床。結構危ない。朝食を食べて、作業開始。 とはいえ、今日は 某大学 O岡山キャンパスに行くので 11:30 ぐらいには中断して家を出た。

目的のキャンパスに到着すると、時間がちょうど昼時になっている。 なんか前言った場所では昼休憩の時間だった気がするので、ちょうどいいし自分も昼飯を食べてから部屋に向かうことにした。 麵屋こころの本店がここにあるらしいという情報をキャッチしたので、向かう。

f:id:spider_0859:20210710161614j:plain:w370
麵屋こころ本店。美味しかった。

麵屋こころ自体久々に食べたのよう沁みる。 本当に美味しかったのだが、ちょっとした方針で店員同士が揉めててちょうどその間が僕の座っている位置だったのだけが困った。 麵屋こころのまぜそばはかなり美しいのでブログに記録したくなるな。

色々あってかなりかなり帰りが遅くなる。 もっとチャチャっと終わる用事だと思っていたのでかなり疲れた。

20:00 ごろ、帰りの電車で TCO の話題になっているのに気づく。 そろそろ TCO Round 3 の時期かと思って CLIST を確認すると、7 分後とかなっていた気がする。 マジで心臓がなくなった。 因みに普通に電車内なのでもうどう抵抗することもできずにそのまま諦めた。 クソみたいなスケジューリングミスで大切なコンテストの出場失敗するのは金輪際辞めたいと思った。

帰って失意のまま夕食をたべた。 そのまま就寝しようと思ったが、自分がかなり解釈に困っていた E - White and Black Balls についての話題が Twitter であったら熨斗袋さんが鏡像法で考えると分かり易い(?)旨のリプライをいただいた。 鏡像法って言うと、あの $ 1 $ 年の頃に物理学をやっていて、鏡像の点電荷を想定することで見通しが良くなるような計算手法だった気がするなあと思いながら 結局どこら辺が嬉しいのかいまいちわからず、その旨を返しておいた。

どうやら、鏡像法についての何かを書いてくれるようなので勝手にかなり期待している。

07/09 (FRI)

11:20 起床。勤務じゃない日なので当然起きられない。こういう日もちゃんと起きられる体になりたい。 今週は色々なことがあって疲れた。こんなことで疲れちゃだめだと思っていても疲れたので、朝飯を食べたら 読んでいないで溜めてしまった漫画作品の消化などをする。

先日、潮が舞い子が舞いの最新刊が 7/8 に発売されていることに通知で気づく。 即刻購入する。ジャンプは紙派なのだが、すべての読んでいる漫画を紙で持っているのは割と無理があると思ったので新しく買い始めた漫画は殆ど電子書籍版を購入している。

潮が舞い子が舞いは確か部隊は兵庫のあたりの田舎の高校生たちの話で、ジャンルで言えばいわゆる登場人物がたくさんいるタイプの日常系だ。自分はキャラが多い日常系作品は取っ散らかってて苦手なのだが、この作品は各キャラごとの関係性がちゃんと描かれていて、ナマモノな感じがとても好みだ。ついでにナマモノ系作品ってシリアスだったりして読んでいてつらかったりすることが多いのだが、この作品はシリアスすぎず(というがギャグなので)かなりこの作品からしか摂れない栄養素があると思う。

なぜこんなことを記録しているかというと、金曜日は週記に各内容がないよう、なのだ。 いつも通り 14:30 から TA をして、それが終わったら続きでゼミがある。 それを終えればもう 19:00 前とかそんなんなので、字に起こすとかなり退屈な曜日だ。 当然だが、ゼミで面白い論文が読まれれば、ちょっと調べものをしたりしてそこそこ知識が増えたりもするので 字面ほど退屈な日ではない。

夕食後、確認を忘れていた怪獣 8 号をチェックする。 現在、隔週連載になってしまっているのでもっと大切に読むべきかどうか悩んでいる。 大切に読もうと思った結果、確認を忘れまくってもう話がどこまで進んでいたのか忘れてしまうケースもあるので本当に悩みどころである。ちなみに SPY FAMILYはためすぎてこれになっている。

夕食後なにかをしようと思っていた気もするが、特に書くほどのことはしなかったように思う。

一応 D - サプリメント を解いた。

問題概要。サプリメントが $ N $ 個あり、$ M $ 種類の味ある。サプリメントには $ 1 $ から $ N $ の番号が付けられており、若い番号順に高橋君は摂取する。$ 1 $ 日にいくつでも高橋君は摂取することができるが、 同じ味のものは飽きるので食べられない。この時、すべてのサプリメントを食べる食べ方は何通りあるか。$ \pmod {10^{9}+7} $ で答えよという問題。

$ N,M \leq 10^{5} $ という制約。まあこんなものは DP で考えればいいので考えると、特に持つべき情報がなさそうで一次元の DP が見える。ただし、高橋君がその日にどれだけのタブレットを食べるかが遷移なので、遷移が $ O(N) $ になってしまい計算量が $ O(N^{2}) $ になる。ちょっと考えると、「被りがないよう連続領域を取る」みたいなのは尺取り法の典型だ。ある左端を固定したときの被らない区間を求めてそれに全て遷移することになる。遷移が連続区間なので、高速化はどうとでもなる。セグ木系を使ってもいいし、今回は区間に対して加算の寄与なのでいもす法っぽく DP をすると速い。 いもす法っぽく DP をするときは初期化に注意したい。$ dp[0] = 1 $ だけでなく $ dp[1] = -1 $ も必要だからだ。

やる気が起きな過ぎて親の酒を強奪して飲もうと思ったが、全然缶のものがない。 去年家で作られた梅酒がまだ少しあるので、それを飲むことにした。 コップの半分もなかった。かなりひもじい。

f:id:spider_0859:20210710170149j:plain:w300
ウチの現存する最後の梅酒。

さて明日は学科の発表系イベントが 10:00 からあるので就寝。

07/10 (SAT)

9:55 起床。アラームをかけ忘れていて起きた瞬間、心臓がブラジルまで行った。 なんとか学科のイベントに間に合う。 本来自分が出ても意味ないだろみたいなイベントとはいえ、出ないと怒られるので本当によかった。

このイベント、M2 の中間発表などに対して M1 が質問をしなければならないのだが、研究室の違う(専門の違う)M2 の先輩の研究なんて質問が出来るほど理解できるわけないだろと思う。というかそれがどこの馬の骨ともわからない M1 に理解されていたら、そのテーマで修士号をもらえるか怪しいだろ

愚痴を言ってもしょうがないので、速攻ノルマである $ 3 $ つの質問をこなした。 ところで、今日はついうっかり昼過ぎに散髪の用事を入れてしまったので質問もこなしたし、つないだままちょっと抜け出した。 大分スッキリした。帰ってきてもまだイベントを続いていたので安心した。

イベントが終わる。ここで、週記を溜めていたので現実に追いつかせておいた。

せっかく散髪したので、枕カバーについている死んでいった毛たちをコロコロで丹念に処理しておいた。 結局その夜寝たら髪の毛が付着しまくった…

夕食を食べ終わって、のんびりしていた。 ABC を完全に忘却していた。やっちまった…。完全に日曜日だと思っていました。

$ 50 $ 分遅刻ぐらいで問題を見たが D 問題まではすぐに解けた。C 問題がいつもより難しく感じた。 E 問題がむずそうだった、時間が足りなかったが多分解けているので時間が出来たら書こうと思う。

悲しい気持ちになったので、Div.3 を出ないで寝ることにした。

07/11 (SUN)

8:30 起床。今日は友人宅に行くことになっていたので支度をして出かける。

詳細は省くが、今日は友人宅に行って昼夜はスパイスカレーを作って食べた。 正しく言うと、俺はスパイスカレーの知識が全然ないので観察担当者です。

f:id:spider_0859:20210712134058j:plain:w280f:id:spider_0859:20210712134103j:plain:w280
スパイスカレー。美味しかったです。

久々に高校同期の友人に会えたので満足しながら帰宅。 コドフォ Div.1 があったらしいが気にしない。というかそれに出ないことをなんとなくわかって今日は過ごすつもりだったので。

帰り道に Twitter を見ると、典型 90 の閉会式をやっていた。E869120 さん、お疲れ様です。 というわけで、一応帰宅してから週を終えることができた。

ちなみに、友人宅で競プロの問題を少し解いたので Streak に関しては心配がない。 D - 一刀両断 がその $ 1 $ つだが、これ普通に難しく感じた。 まあ、自分の場合は幾何ライブラリを整えているので、線分同士の交差判定をすれば良いのでいいが、0 から作ると大分しんどそう。 ccw をソラで実装できるし、まあそうでもないかな。よくわからないです。

東京に行くと疲れるのか、毎回就寝がちょっと早くなる。

週記(2021/06/28-2021/07/04)

06/28 (MON)

9:00 起床。夜更かしをしたのに意外と眠くないし、体調も悪くない。 朝ごはんを食べながら今日の典型を確認する。

https://atcoder.jp/contests/typical90/tasks/typical90_bz

問題概要。$ N $ 頂点 $ M $ 辺の無向グラフが与えられる。 自分より頂点番号の若い隣接頂点が $ 1 $ つだけ存在するような頂点の数を答えよ、という問題。

それぞれの辺に対して、頂点番号が大きい方に $ +1 $ カウントする配列を構成して最後に配列を舐めて、$ 1 $ の要素数を数える。 $ O(N+M) $ で解けるし、グラフを構成する必要も実はない。構成した方が慣れ親しんだ手法な気もするが。 キーワードがわからない。「隣接頂点全探索は辺の数のオーダー」とかですか、わかりません。

わからないながらも大学に向かう。時計をどっかにやってしまってめちゃくちゃ QoL が下がっている。 行きの電車内では昨日の AGC-B を改めて見て考えていた。 挿入 DP は昨日散々考えて不可能であると判断したのでのんびり眺めた。

ちょうど全体の和の半分になるような subset を考えた時にその subset を高橋くんが取る場合の数に思いを馳せた。 高橋くんがとらない数字は青木くんが取る。それぞれの subset を独立に並び替えてその順番で取ることを考えると、それぞれの並べかえと 数えたい順列が一対一対応することがわかる。気づいてしまえばボケ簡単だった。

昨日ちゃんと解けた C といいこの B といい、順列の数え上げというありふれたテーマなのにパターンマッチへのアンチテーゼのようで、AGC の問題の質の高さを感じた。

大学に着いたらいつものケイジャンチーズ牛飯を購入してモンスターエナジーとともに摂取する。 食べ終わる時間ぐらいに、ゼミが開始する。今日も B4 の発表回。いい意味でも悪い意味でもスライドにそれぞれの個性がでているなあと思った。 去年の僕もこんな風に見られていたと思うと震えちゃうね。

f:id:spider_0859:20210629120424j:plain:w300
今日のセブンのおやつ。先週から試してるんだけどこれがおいしい。

ちなみに今日のおやつにはいつも通りプリンを買ったのだが、先週から試しているこれがかなり美味しいと再確認した。 三層になっているのだが、一番上がチーズケーキっぽく、真ん中はクリームで、一番下がプリンになっている。

そんなこんなで作業をしていた。今日は途中で先輩方と話こみ、様々な話になった結果、色々な知見とかが得られた。 話の話題に出て読もうと思った論文を Paperpile: Modern reference and PDF management - Paperpile に入れた。 こういうののために研究室に行っているというところが大いにある。本当は頻度を増やしたいと思っているんだけど、研究室に行く日はほぼ確実にピアノの練習ができないため、中々難しいところである。

帰ると 22:00 ぐらい。夕食をむさぼる。 夕食後、上に書いた AGC-B の解法で書いて通した。これで通らなかったら上の解法を消さなければならないのでほっとした。

06/29 (TUE)

11:00 起床。正しくは、9:00 には起きていたのだが布団の中でもぞもぞする時間が長すぎた。

今日の典型を確認する。★3 だ。

https://atcoder.jp/contests/typical90/tasks/typical90_ca

問題概要。$ H \times W $ の二次元配列 $ A,B $ が与えられる。$ 4 $ マスの正方形領域に対して一括で $ \pm 1 $ をする操作を行うことが出来る時、$ A $ を $ B $ に一致させることが可能かどうか判定せよ、という問題。

蟻本には $ \mod 2 $ の世界での問題(正方形フリップ)が載っていたような気がする。 今確認したら蟻本 p.141 にそれらしき POJ の問題が載っているのだが、自分の記憶より難しい問題だった。 こういう問題は、端から見ていくとそこで操作を行うべきかが一意に決まるため貪欲に解ける。具体的に言うと、上にも左にも不確定なマスがないようなマスが左上になるような正方形領域に何回操作をするかは自明にそのマスの値により一意だ。 蟻本のやつは、$ 3 \times 3 $ の正方形領域だったため $ 1 $ 行目を決め打たないと一意にならなかったが、この問題ではその心配もない。

バイト先の slack からの返信を確認した。確認しながら、サボってた時期の典型をちょっと見ることにした。

059 - Many Graph Queries(★7) とにらめっこをすることにした。

問題概要は簡単。$ N $ 頂点 $ M $ 辺の DAG が与えられて、頂点 $ A_i $ から $ B_i $ に到達可能かどうかのクエリ $ Q $ 個に答える。 sample の隣接行列を書いてしばらくグッと睨んでいた。

しばらく睨んでまともな解法がなさそうなことに気づき $ 64 $ bit をまとめて処理することを考える。 到達可能性の行列は頂点番号の降順(トポロジカル順序の逆順)に構築可能だ。 $ u < v $ であるような頂点 $ u,v $ を考えたときに、$ u $ の到達可能性を bit vector で考えたとき、 $ u $ が $ v $ に直接到達可能ならば、 $ v $ の到達可能性の bit vector との OR で更新すれば良いことが分かる。直接到達可能な頂点数は辺の数の $ M $ と一致するため、全体で到達可能性行列は $ O(MN) $ で前計算出来る。 OR をとるパートで $ 64 $ bit ずつ処理すれば $ 64 $ 倍速くなり、多分間に合うのだろう。まあ $ 64 $ bit というかワードサイズなのだが…

ここで書き始めるも、Memory Limit を思い出し計算すると $ 1200 $ MB ぐらいかかりそうなことが判明。最悪や。 冷静になると、DAG の到達可能性なので、$ M _ {i,j} \quad (i \leq j) $ の部分だけあれば十分なので大体半分ぐらいになるから足りそう。 この手の高速化は結構カツカツな状況が多いので offset やブロックのインデックスを求める時に割り算を使うと終了しそう。ワードサイズは当然二冪なのでビットシフトや AND を使おう。でも二冪定数の割り算ぐらいビット演算に最適化してくれそうだけど…どうだろ…

色々工夫して頑張って書いたら $ 500 $ ms を割ったので、記念にソースを貼っておく。 まあ測定結果とかキャッシュミス率とかを監視しながらチューニングをしたわけではないのでもっと速くなるかもしれないけど。 やったことを箇条書きしてみる。

  • 最大ケースで使用するサイズを事前に求めて、そのサイズでメモリプールをグローバル変数で静的確保。
    • malloc でいちいち確保をすると free も面倒だし困る。今回途中で解放や再利用はしないためこれでいい。
    • bitset が全て連続領域なので多少高速化に寄与する可能性あり。
    • マージの時に連続領域だと次の bit vector の先頭ポインタを使うことで楽に後ろから OR を取れる。
  • Fast IO … 入力を一括で静的領域に受け取り、自分でパース。出力はバッファリングして最後に一気に write & flush する。
    • $ 10^{5} $ 行ぐらいあるので、間で何回も flush すると遅そう。入力もそこそこ多いけどこっちの影響は不明。
  • 最適化オプションは O3 にした。何か起これと祈る。

▶ソースコードを展開

そして、毎週恒例のピアノしばき。今週は、最後まで譜面の流れの把握が終わった。 ここからは只管にスムーズに綺麗に速く弾けるかを、訓練によって伸ばしていくパートなのである意味気が楽。

夕食まで少し時間があったので論文を読む。集中力が持たないので終了。

夕食のあとは通話をする用事があったのでする。 そういえば、この前研究室の先輩がやっていたため初めて知ったんだけど、zoom ってスペースキーを押しながら喋ると一次ミュート解除ができるらしい。これを使えば色々な場面で誤爆を起こしにくいし、わざわざどっかに行ってしまった zoom の窓を探してミュートボタンを解除する作業が必要なくなる。 自分は感動したんだけど、実はみんな知っていたりしますか?

通話が終わる。もうなんか今日はいいかという気分になる。 競技プログラミングの問題を一問通してもうだらだらすることにした。

D - アルファベット探し

問題概要。$ 7 \times 7 $ のサイズの $ A,B,C $ の文字のドットパターンみたいなのが与えられる。 これが $ 90 $ ° 単位で回転したり、相似比が正整数になるような拡大が可能である。 大きな図面 $ H \times W $ が与えられるので、それぞれのアルファベットの出現回数を答えよ、という問題。

拡大があるので、真面目にパターンマッチングっぽいことをすると工夫が必要な上、かなり怠い(というか完成させられるか怪しい)実装になりそうだ。 こういう問題は色々な側面からそれぞれのパターンの特徴が得られないかを観察する。 一番ありがちなのは塗られているマスの数とかである。 今回も数えてみると、$ 7 \times 7 $ の $ A,B,C $ の塗られているマス数はそれぞれ $ 12,16,11 $ だ。 これらの数が正整数の相似比で拡大されるので、任意の正の平方数を掛けてもユニークか確認すると、しっかりユニーク。 パターン同士が重なることはないと制約にあるので $ 8 $ 近傍を接続した連結成分のサイズを確認すればいい。 DFS を用いて実装するのが楽で、 $ O(HW) $ の計算量で計算できる。

パターンから取りやすい特徴を抽出して判別をする問題、ICPC のフィリピン地区大会で出会ったため一生忘れなそう。 あれは $ A $ から $ Z $ まであったので特徴を抽出する段階でまあまあ嫌だったけど。 今回はひとつの特徴で完全に判別がついたけれど、$ 2 $ つ以上の取りやすい特徴の複合キーで判別することの方が多そう

就寝。

06/30 (WED)

9:30 起床。10:45 分提出のショートレポートを書く。 物理っぽい内容が含まれている講義なので、大分懐かしく感じる。 情報工学をしているとマジでいわゆる理系っぽいことは何もできなくなっていく。 大学受験化学なんて多分 $ 8 $ 割はもう忘れている。

ショートレポートを書き終えて朝食を食べながら、今日の典型を確認する。★6。

https://atcoder.jp/contests/typical90/tasks/typical90_cb

問題概要。$ D $ ビット以内で表現可能な正整数の列 $ A $ が与えられる。$ A $ の全ての要素との AND が $ 0 $ でないような整数 $ x \quad (0 \leq x < 2^{D})$ の数を求めよ、という問題。

制約を見ると $ N \leq 20 $ で $ D \leq 60 $ だ。こんなんもう桁 DP やるだけではないでしょうかとなる。 bit DP との複合だから難しいということなのかなとか思いながら DP を組む。 $ dp[i][S]$ : $ i $ 桁目まで $ x $ を決めて、$ A $ の各要素との共通部分を持っているかどうかの bit vector が $ S $ の時の場合の数。

この DP は状態数が $ O(DN) $ である。愚直に遷移すると $ O(N) $ かかる。 ここで初めてこの出題の意図を理解する。このままでは計算量が $ O(DN^{2}) $ でかなり怪しい。 事前に $ B_i $ : $ x $ の $ i $ 桁目を $ 1 $ にすることで共通部分を持つことの出来る $ A $ の要素の集合、つまり $ i $ 桁目のビットが立っている要素の集合の bit vector を前計算することで、遷移が $ O(1) $ になり計算量は $ O(DN) $ と余裕になる。 よく考えると、昨日の日記で解いたワードサイズ定数倍改善と同じ。 でも定数倍改善かなり頑張ればそのままでも通ったりするかも

典型が解けて安心しながら多少作業をするも、ピアノがあるのでピアノをしばく。 レッスンに行く。下手くそ。以上。頑張ります。

帰ってきてからは、主に競プロをやっていた。作業もちゃんとした。 夕飯を食べたあとはカプリティオチャンネルの動画を見ていた。

www.youtube.com

僕自身は全然競技クイズはやらず、たまにみんはやをプレイするぐらいの一般人だが、クイズを見るのは好きだし、 カプリティオチャンネル等のクイズ系の YouTube チャンネルはしっかり一般人にも楽しめるように作って合って見やすい。 最近ちょっと YouTube でもこうの短い動画以外のものを見る時間がとれていなかったので面白そうなものから消化していった。

ここで slack を確認すると、研究室内で濃厚接触者が出たらしく(感染者というわけではなさそうだが)、 とりあえず二週間ぐらい全てがオンラインで行われて、かつ研究室にもなるべく行かないようにというメッセージが来ていた。 二週間の間、ケイジャンとはお別れの様だ。というか二週間多分地元すら出ないことが確定した。

嘘をついた。3 日にはワクチンを接種しに行く予定である。なんなら、他の外出の予定も既にあった。ショックで一瞬全てを忘れていた。

■■■■■の予定表を入れなければならなくて、これがなかなか自分が微妙に忙しいせいで埋まらなくて困っていた。 正直困り果てていたが、催促のメッセージが来てしまったのでちょっと無理っぽい感じに入れて後でいろんな人にお話をしなきゃだめかも… こういうなんか懸案事項が複数ある状態って死ぬほど嫌いで、耐えがたい。こういう時の精神の持っていき方が $ 23 $ 年ちょい生きてて一ミリもわからねぇ。

あと、書類って何で一意解釈できない項目のオンパレードなんだろう。 本当に助けてほしい。普通の人間がこういうのを普通にこなしていると思うと信じられない。HELP!!!

取り乱したが、明日は朝に大切な用事があるので今日は持参物を確認して寝るか。

寝る前にサボっていた典型を一つ通すか、と 60 を見たら既視感があったので週記を見返したら考察はあった。

右から見て最大値が $ A_i $ になる LIS が欲しくなる。 LIS の DP は $ O(1) $ で revert が可能なので、事前に右からの LIS は計算しておき順次 revert していけば欲しいものが得られそうだ。

週記(2021/06/7-2021/06/13) - むかでの競プロ備忘録

どうでもいいけど、永続配列を使えば revert の必要すらないな。

書き上げた段階で、自分の脳がおかしいことに気が付いた。 普通に revert なんてことをしなくても左右からそれぞれ $ A_1 \cdots A _ {i - 1} $ と $ A _ {i+1} \cdots A_N $ の LIS の長ささえわかれば答えが出るので、左右から DP するだけ問題でした。う~んこの…

07/01 (THU)

7:10 起床。大切な用事があったのでちゃんと起きられて安心した。 雨がしっかりを降っている。

支度と朝食を済ませて目的地に向かう。行きの電車で今日の典型を確認する。★5。

https://atcoder.jp/contests/typical90/tasks/typical90_cc

問題概要。$ N $ 人の生徒がいて、 $ i $ 人目の生徒の身長と体重がそれぞれ $ A_i, B_i $ となっている。 チーム内のどの $ 2 $ 人を取ってきても、その身長の差・体重の差が $ K $ 以下であるようなチームを作りたい。 作れるチームの最大人数を答えよ、という問題。

実は昨日より悩んでしまった…。昨日のは着眼点を間違わなければ処理するだけの問題だったが、今日はどこに目をつけるかが難しいように感じた。 $ A_i, B_i \leq 5000 $ と $ K \leq 5000 $ という制約があることに気づく。 ここに注目すると、生徒を二次元平面上に点としてプロットすることができる。 情報のペアや、区間を二次元平面にプロットするのは典型なのでここに詰まったのは反省の余地がある。 この時に条件がどのように言い換えられるかを考えると、$ K \times K $ の正方形領域に入る点の集合なら条件を満たす。 というわけで、二次元累積和を前計算することで $ O(A _ {max} \cdot B _ {max}) $ で解くことができた。

典型が解けた安心感から、後は到着するまでうとうとしていた。 用事のためとはいえ、東京に行くのが久しぶりでテンションが上がった。

初めて行く場所だったので早めに着くように調整したのだが、やっぱり迷う。都会難しすぎるぜ。 まあそこは時間に余裕があったので結果として問題がなかった。 問題なのは雨がメチャクチャに降っていたことだ。 自分の革靴は大分前から履いていて裏のゴムは大分ヘタってしまっている。 その関係で雨の日に滑りやすい地面をあるくとヌゥルヌゥルしまくって怖いのだ。 朝から何回も転びそうになっていたんだけど、ついに目的地の目前で大ゴケしてしまった。 その際に左手首を負傷した。ピアノにも音ゲーにも支障が出そうで心から嫌だった。 あと結構色々な植物が繁茂している場所でコケたので汚れるし周りに人が居なかったので感情を抑えられず声出た。 雨の日にはもうその革靴を履いて外出しないことを誓った。というかいい加減買い替え時なのかもしれない。

最悪な気分になりながらも予定よりも $ 15 $ 以上早くに到着していた。 汚れたズボンとかカバンとかを拭いていたので詳しい時間はあまり覚えていない。

さて用事を終えて昼飯を食べなければ餓死する時間になってしまった。 とはいえ、全然親しみのない土地で飯を探すのに苦労してしまった。 困り果ててキョロキョロしていたのだが、完全に都会に出てきたての田舎の若者ムーブをしていたので恥ずかしい。 普段都会人と行動を共にして自分も都会人のフリをしているのだが、いざ一人になると無力な田舎者ということが暴かれていく。

ダイバーシティという施設が近くにあることは知っていたので、ここに向かうことにした。

f:id:spider_0859:20210701223828j:plain:w300
歩いていると、フジテレビくんを発見。

歩いていると、フジテレビくんを発見した。写真を撮っているところを人に見られて恥ずかしかった。 施設に到着すると、ドラえもんが出迎えてくれた(画像無し)。 中に入るとうんこミュージアムなるものまであった。 飯を探しているのにコレに出会ってしまい、もう顔中○まみれや。

施設内でまたしても迷子になる。エレベーターが探せない。やっとの事でエレベーターと施設の案内みたいなのを発見すると、どうやらマクドナルドがあることがわかった。流石にここにきてマックはないなということですんでで思いとどまり、牛カツの店に入る。念のため言っておくと、チーズ要素はない。

f:id:spider_0859:20210701224525j:plain:w370
牛カツ。ダブルにしたらマジで多かった。おいしかった。

今日は研究室内のミーティングの日なのだが、用事のこともあって帰っても全然間に合わないので開き直ってダブル牛カツ膳を頼む。 シングルだと正直足りないかなと思い上のを頼んだのだが $ 1.5 $ 倍ぐらいのボリュームを想定していたら、しっかり原義ダブルの $ 2 $ 枚きて焦った。ちゃんとメニューを見ろよ。$ 1.5 $ 枚を想像していたので最後の半分は相当苦しかった。

胃の健康のために、施設内のベンチみたいなところで休憩をとってから帰路についた。 胃がいっぱいなのと、東京に対する疲れによって帰りの電車では疲れて爆睡していた。 日本の治安の良さに感謝しながら帰宅。

帰宅してから、作業とかスマホ弄りとかを仕様かと思ったが左手首が痛すぎて横になっていた。 気づいたら寝ていて夕食の前だったのだがワロタで済ませておいた。

食後は今日の典型を書いてきた。二次元累積和で実装するのでその幅は $ K+1 $ でなければならないところを $ K $ にしていて、サンプルが合わなくて $ 5 $ 分ぐらい無駄にした。AC。

C - 高橋君と国家 を解いた。 $ N $ 頂点 $ M $ 辺のグラフが与えられる。頂点 $ v $ を交易所にするのに $ c_v $ のコストがかかり、辺 $ i $ を整備するのに $ r_i $ のコストがかかる。全ての頂点が交易所に到達可能にするのに必要な最小のコストを求めよ、という問題。

交易所にする頂点を確定させたら、交易所を各連結成分に含む最小コストの森みたいなものを求めればいいなとか思う。 制約的に交易所にする頂点を選ぶようなアルゴリズムは無理なので頭を少し捻ると、仮想頂点を置いて、交易所にする操作を仮想頂点から各頂点への辺として考えてしまうと最小全域木問題になることがわかる。あとは書くだけで AC。仮想頂点を置くことで最小全域木になる問題、たまに見るな。

今日もサボり分の典型を処理していく。Deck(★2)

整数の書かれたをデックの上に載せる・下に入れる・上から $ k $ 番目の数字を出力する、の $ 3 $ 種類のクエリに $ Q $ 個答える問題。 マジで std::deque を使うとそのまま。

062 - Paint All(★6)

大分前の典型なので問題概要は省略。 冗談抜きで $ 30 $ 分ぐらいかかってしまった。 初手頂点 $ A_i $ と $ B_i $ を結ぶ辺を張ったグラフを考えたのだが、全然いい筋の解法が浮かばない。 よくよく考えると、$ A_i $ か $ B_i $ のどちらかが白なら $ i $ が黒に塗れるという関係は $ i \rightarrow A_i $ と $ i \rightarrow B_i $ の二辺で表せて、こっちの方が良く特徴の現れたグラフになる。これでも解けなかったので逆操作を考える。全部黒の状態で逆操作を考えると、$ i = A_i $ または $ i = B_i $ のような頂点以外は白く塗れない。これ以外の逆操作は、$ x \rightarrow y $ かつ、頂点 $ x $ は黒、$ y $ は白のような場合に頂点 $ x $ を白く塗ることができる。したがって複数始点の逆辺を辿る DFS/BFS によってすべての頂点へ到達可能なら、問題の条件を満たす。行きがけ順の逆順に出力すれば答え。

速く解けなかった理由は

  • 全然うれしくないグラフへの落とし込みをしてしまった。
  • 操作の前提条件が緩く、結果が明確な操作は順操作がつらく逆操作が楽がちなことを忘れていた。
    • 「遷移可能な頂点のうち少なくとも $ 1 $ つが白なら黒く塗れる」がこれに相当。
    • よくあるのだと範囲塗りつぶしみたいな操作もこれにあたる。(塗りつぶし前は任意色だが、後は一定)
    • 「$ x $ の倍数なら $ x $ で割れる」みたいなのもこれか。

就寝。ところで、探している漫画が見つからずにもやもやしていた。

07/02 (FRI)

9:30 起床。からの 11:45 起床した。最悪。

トーストを朝ごはんに食べた後、今日の典型を確認する。★3。

https://atcoder.jp/contests/typical90/tasks/typical90_cd

★3 にしては大分怠い見た目をしている。問題概要。$ L < R $ であるような正整数 $ L,R $ が与えられる。$ x \in [L,R] $ の $ x $ を $ x $ 個ずつ黒板に書いたとき、黒板に書かれている数字の数を答えよ、という問題。 数字というのはどうやら桁のようだ。

$ L,R \leq 10^{18} $ なので愚直系は全部アウト。桁ごとにやるしかなさそうだ。例えば $ 1 $ の位の寄与を考えると、 $ 1 $ 以上の整数の和になる。これ難しくないか? 閉区間 $ [L,R] $ に対して問題を解くのは面倒なので、$ [0,X] $ の問題を解けば $ [0,R] $ の答えから $ [0,L - 1] $ の答えを引いてよし。 なぜかもうジャッジが来ているので提出して AC。

一般の閉区間や半開区間の問題を $ [0,X) $ の問題に落とすことで幾分か楽になるの多いな。

サボり分の消化。063 - Monochromatic Subgrid(★4)

問題概要は省略。こういう問題は片方の軸について固定するともう一つが簡単な問題に落ちることが多い。 制約を見ると $ H \leq 8 $ なので行についてその行を選択するかどうかを決めうつことにする。$ O(2^{H}) $ で決めうてる。 すると、各列に対して取る行について全て同じ数字でない列はそもそも選べない。 また、出現する数字が同じ列のみを同時に選択することができる。 よって std::map などによって、それぞれの出現度数をカウントしてやれば、$ O(2^{H} HW \log{W}) $ とかで解ける。AC。

昼飯を食べる。焼きカレーとかいうの最高にうまい。

064 - Uplift(★3)

問題概要省略。区間加算操作の前後での隣接差の変化は区間の端 $ 2 $ 箇所にしか現れない。これが全てだ。初期状態の「不便さ」と、隣接差(符号付)を計算しておいて、あとは端に関して隣接差と「不便さ」を更新していくだけだ。区間加算が $ 2 $ 箇所に対する操作に言い換えられることは難しめの問題でもよく出る内容な気がする。 区間加算だけじゃなくて区間 xor でも出題がある

065 - RGB Balls 2(★7)

問題概要省略。★7 はやはり結構難しい。赤・緑・青のボールを取る数をそれぞれ $ r,g,b $ とすることによって立式することができる。

$$ \left\{ \begin{align} &r \leq R, \quad g \leq G, \quad b \leq B \quad \cdots (1) \\ &r+g \leq X, \quad g+b \leq Y, \quad b+r \leq Z \quad \cdots (2) \\ &r+g+b = K \quad \cdots (3) \end{align} \right. $$

見てすぐに $ O(K^{2}) $ の解法は思いついた。これは $ r,g,b $ の内 $ 2 $ つを決めうつことによって、式 $ (3) $ によって残り $ 1 $ つも確定する。その $ r,g,b $ が上の全ての式の条件を満たすかチェックして、満たしていたら $ \binom{R}{r} \binom{G}{g} \binom{B}{b} $ だけ答えに寄与させれば良い。

当然この問題の制約では $ 2 $ 乗は間に合わないので、工夫が必要。 $ 2 $ 色のボールに関する不等式制約がかなり煩わしいと思う。グッと睨むと $ (3) $ を使うと $ 1 $ 色のボールの制約にすることが出来ることに気が付く。これを整理すると、

$$ \left\{ \begin{align} &K - Y \leq r \leq R \quad \cdots (4) \\ &K - Z \leq g \leq G \quad \cdots (5) \\ &K - X \leq b \leq B \quad \cdots (6) \end{align} \right. $$

のような制約が得られて、これはかなり分かり易い。$ r $ を決めうってみる。この時に $ g + b = K - r $ であるような場合の数が高速に求められれば解ける。 式 $ (5),(6) $ に注意しながら、有効な $ b,g $ について、$ \binom{G}{g} $ や $ \binom{B}{b} $ の配列を構成すれば、その畳み込みをすれば欲しいものが手に入る。FFT を使えば $ O(K \log K) $ でできる。結局ボトルネックFFT なので、この計算量で解けた。AC。

目的意識を持って、一直線に式を変形するの難しいな。今回は $ 2 $ 変数に関する条件を $ 1 $ 変数に関する条件に変形可能。 こういうのはどこまで行っても ad-hoc になってしまうため、変形の目的と実際の変形のパターンの引き出しをたくさん持っておくのが良い気がする。

あといい加減自分の FFT を作ろうかなと思うんだけど、FFT は定数倍が結構センシティブな気がしていてなかなか… ところで 059 - Many Graph Queries(★7) の想定解について触れる。 想定は、隣接行列を更新していくのではなくクエリを $ 64 $ 個ずつ処理するものだった。背景としては、到達可能性の配列は $ bool $ 型の配列なのでワードサイズの $ 64 $ クエリまで重ね合わせることで速くなるというやつだ。こちらは MLE が気にならないので賢い。

066 - Various Arrays(★5)

問題概要は省略。全ての $ i < j $ を満たす $ (i,j) $ について、$ A_i > A_j $ であるような確率を足し上げた者が答え。 いわゆる期待値の線形性とか、主客転倒とか言われているテクニックな気がする。 期待値の問題は期待値の線形性を利用しない問題はほぼないのではなかろうか。 ちなみに上の実装を完全に全探索で行っても $ O(N^{4}) $ で間に合う。ちょっと工夫をすると $ O(N^{3}) $ になって、頑張ると $ O(N^{2}) $ になると思うが、出題側も主客転倒が問いたいだけなので非本質ということなのだろう。

連続して消化作業をやっているように見えるが、途中に TA 業務やゼミが挟まっている。 TA といえば今週は $ 2 $ 人も質問に来た。心なしか他の TA にも普段より質問が来ているように感じた。 今回の Java の講義内容がテストとラムダに関する内容だった。 学部生ということもあって、テストがどういうものかわかっていなくて混乱するみたいなケースが多そうと感じた。 研究室に来るまでにはちゃんとわかっていて欲しいと思うレベルの解説をした。説明うざいと思われていたら立ち直れない。 壊れている素数判定関数の単体テストを書くみたいな課題が出ていて、最低 $ 2 $ つのテストメソッドを書けとのこと。 何をどうテストしていいのかわからず、正しい素数判定をして $ 1 $ から $ 100 $ までの整数で比較するみたいなメソッドを書いて、もう $ 1 $ つ何を書けばいいのかわからない、とかそれに近しい質問が $ 2 $ つだった。 気持ちはわかるが、その「正しい素数判定」が正しいということを保証をしてくれるものがないので、テストとして不適切ということを言って、こういうのはシナリオ別に分けてメソッドを記述するからこの場合最低でも素数と非素数の $ 2 $ つのテストが必要で、その入力と出力に関しては人間が計算・判断したものを入れる、と言ったら納得してくれた(と思う)。まあ正しくはこれはブラックボックステストなのだが、ブラックボックステストホワイトボックステストの話まで始めたら流石に嫌われると思ったのでやめた。

典型の消化作業続行。067 - Base 8 to 9(★2)

$ 8 $ 進数 $ \rightarrow $ $ 10 $ 進数 $ rightarrow $ $ 9 $ 進数をする関数を定義して、$ K $ 回実行する。 投げると $ 1 $ ケース落ちるのでよく見ると入力に $ 0 $ があるので、$ 0 $ の時に空にならないように直すと通る。 この手のの問題で $ 0 $ があるの本当に不愉快だな。悪口ではなく負け惜しみです。

食後に yukicoder contest 302 - yukicoder があるので出る。

A 問題。最初指数結合法則が足し算だと思っていた(腦)。冷静になると掛け算で、デカいな~と思いながら $ \mod 10^{9}+6 $ を取ってやってから二分累乗をする。

B 問題。この問題難しい!$ (0,0) $ が負け、から遷移を書いたり思い浮かべたりしてガチャガチャ弄っていると証明できそうな構造が見つかる。証明出来て投げる。コーディングミスで 1 WA もらう。

C 問題。最初に与えられた整数の $ \mod 10^{9}+7 $ を求めて $ S $ とする。 $ S $ 以下で $ A^{n} $ 以上の数字の数が $ \left \lfloor \log _ {A} k \right \rfloor \geq n $ を満たす $ k \in [1,S] $ の数。 よって $ 1 \leq n \leq \left \lfloor \log _ {A} B \right \rfloor $ について $ S - A^{n} + 1 $ を足し上げる。

D 問題。一目で $ 2 $ 乗の DP は思いつく。$ dp[i][j] $ : 和が $ i $ で初項 $ j $ の倍数でなければならないような条件を満たす列の数、とする。$ i $ の約数しか遷移が進まないので、遷移を含めた計算量が $ O(M^{2} \log M) $ になる。よく考えると、$ i $ の約数にしか遷移しないので、$ i $ と $ j $ を $ \gcd(i, j) $ で割っても結果が同じことを利用して $ j=1 $ の状態のみを考えることができ、結果状態数が $ O(M) $ になるので、$ O(M \log M) $ で解けた。

E 問題。最初 sample だけを見て、何も考えずに $ 2 $ - 彩色をして少ない方の数を提出した。WA。それはそう。 よくよく考えると解の下界は最小店被覆である。 そして、これは後手が黒く塗りたい頂点以外を優先的に白く塗ることによって達成可能。

FG 問題。前半に時間を使いすぎて考える時間がなかった。復習する。

A はマジで早く解けなきゃいけなかった。というかこれは知っているだろ… B は初手実験を選べなかったのがかなり痛い。これ帰納的じゃなくいい感じに導けるのかな? C も $ 10 $ 進数ではよく問われる問題なのにまごまごして良くなかった。 D は多分こんなもんだけど、スタックオーバーフローなのか手元では Runtime Error ぽかった。 こんな時、minGW くんはうんともすんとも言わないので本当にゴミ。 WSL 環境にした方が絶対にいいなと思う瞬間である。 E は適当をやっている時間がもったいない。あとはトチ狂って Dinic 法で解いたが木の最大マッチングは 木 DP で高速に書けるようにしたいね。

ここら辺の問題を高速に処理できるかどうかが、今の自分の競プロで大切なことな気がする。 明日はワクチン接種なので早めに就寝。

07/03 (SAT)

9:30 起床。今日はコロナのワクチンを打ちに行く。

典型を確認する。

https://atcoder.jp/contests/typical90/tasks/typical90_ce

問題概要。$ N $ 頂点 $ M $ 辺の単純無向グラフが与えられる。$ Q $ 個の以下のようなクエリが与えられるので順番に答える。

  • 頂点 $ x $ の色を出力する。その後頂点 $ x $ とその隣接する頂点を色 $ y $ で塗る。

難しいぜ。クエリ平方分割が脳裏によぎったが面倒すぎるし、かなり計算量が怪しいので実装する気が起きなかった。 途中インキチ解法を思いついたが当然のように嘘だったので、泣いていた。

さて、ワクチン接種の時間が近づいてきたので支度をして三田キャンパスに向かう。 田町駅で降りて、初手方向を間違えた。ちなみに Google Map を見ていたのに間違えたので本当に人間になりたい。

キャンパスに着くと、ワクチン接種の列ができている。 サークルの後輩がすぐ前にいたので退屈しなかった。最も、退屈するほどの時間待つこともなかったが。 長い列のように感じたわりにすぐワクチンを接種できる。筋肉注射は初めてだったので怯えていたんだけど、マジで何も感じなかった。 電車のシートの隣にマッドサイエンティストが居てヤバイウイルスを筋肉注射されても多分気づかないぐらいには何も感じなかった。

↓はめちゃくちゃ焦っている時のツイート。ちなみにしびれはすぐに取れた。

接種が終わった後に後輩と一緒に三田製麺所で昼食をとった。

f:id:spider_0859:20210705141006j:plain:w350
三田製麵所。久々につけ麺を食べたのでよう沁みた。

昼食の後は、日吉に行った。ゲームもした。帰宅。 コドフォも今日はあるのだが、接種直後なので遠慮しておいた。 就寝。

07/04 (SUN)

11:00 起床。なんだか、副反応ぽかったので念のためゴロゴロしていた。 散々ゴロゴロした後に、熱っぽかったら一応家族に報告の必要があるなと思って体温計を持ってきて測ったら $ 38.4 $ 度だった。 普通に熱があってワロタ。元気いっぱいだったので。確かに少しボーっとしていたけど、低気圧のせいだと思っていた。

そんなわけで ABC の時間まで本当にゴロゴロしていた。AtCoder Beginner Contest 208 - AtCoder に出る。 後で出たことを後悔することになる。

A 問題。$ A \leq B \leq 6A $ なら "Yes"

B 問題。こういう場合は大きい硬貨からの貪欲で良い。もっとキツイ条件でも貪欲が適用できるが、まあ今回はいいだろ。

C 問題。満遍なく配る問題。$ a_i $ が小さい順に国民をソートして最初の $ K' $ 人に $ +1 $ 個キャンディを配ればいい。

D 問題。数え上げるものをよく睨む。$ k $ が小さい順に計算して $ 1 $ 頂点ずつ経由点を増やしながら計算することを考える。ワーシャルフロイド法と完全に一致しているので、ワーシャルフロイド法の過程の要素を足し合わせればよい。

E 問題。落とした。今思えば普通に熱のせいで脳が多少不調だったのかもしれない。いや、そうであってくれ。 $ 10 $ 未満の積ということには一瞬で気づく。次の瞬間に $ 2,3,5,7 $ しか素因数がないことに気づく。TDPC のサイコロ?みたいな問題と似たような感じで素因数の数を状態に持っていれば解ける気がする。次元の数がすごいことになる。設計をかなりミスっていて、あれこれやって雑に次元とかを増やしまくった結果、TLE と相成った。結局落とした。最悪。

とは言え、最近方針一瞬だけど実装が結構嫌だなみたいな問題が ABC で出題されるようになってきた気がする。

F 問題。読んでない。

またレーティングをちゃんと下げた。最悪だけど、今回は副反応中に出た自分に責任があり、涙…。

今週は悲しみの内に終了。

週記(2021/06/21-2021/06/27)

06/21 (MON)

9:30 起床。眠い。昨日の夜はとりわけ暑かったので睡眠の質の低下を感じる。

今日は先日(だいぶ前だが)失くした Suica の再発行をしてから大学に向かった。 記名式 Suica の再発行は手数料さえ払えば完全な復元が可能になる。 事前に手続き自体は済ませておいたので、今日は引き換え券を持って行って実際にカードをもらうだけだ。 みどりの窓口に取りにいくのだが、先客がいる。 何やらチケットを買おうとしているのだが、これが長くてモヤモヤしてくる。 チケットは多くの場合、インターネットやら他の券売機で買えるし窓口の対応する人とのコミュニケーションも円滑とは言えず 12 分ぐらいかかっていた。 ちなみにその後の自分のカード受け取りは身分証明書を見せてものの 2 分で終わった。

みどりの窓口はチケット対応するだけの窓口を作ってくれても良くないか?って千年ぐらい前から言っている。 まあそんなに人いないんだろうけど。

今日の典型を確認する。今週はちゃんとやるぞ。

https://atcoder.jp/contests/typical90/tasks/typical90_bt

問題概要。$ H \times W $ のグリッドが与えられて、それぞれのマスは山か平野である。このグリッドに鉄道を引きたいのだが、 平野にしか線路はひけず、かつ始点と終点が一致してそれ以外では同じマスを通らないような鉄道しか引けない。 最長の鉄道が通るマスの数を求めよ、という問題。

結構エグい問題が出てきたなあと思ったが、$ H \times W \leq 16 $ という制約を見てハイ、となった。 というか冷静に考えると最長路問題に落ちるので効率的な解があってたまるか。 全ての始点に対する全てのパスを DFS で探索する。最後に始点に戻ることができる場合、そのパスが含む頂点の数を答えに寄与 (chmax) する。 流石に全てのパスは多いかもと思うかもしれないがグリッドグラフのパスの数はかなり少ない。 実際に後で今回の問題での自明な最大ケースである $ 4 \times 4 $ グリッドで平野しかないパターンで再帰関数が呼ばれた回数を数え上げたら $ 28,512 $ だった。 最悪でもこれの $ 4 $ 倍程度の計算量しかかからないので、余裕で間に合う。

グリッドグラフのパスの数の見積もりって難しいなと思って、ついでに大きくして検証した。 $ 5 \times 6 $ の場合に再帰関数の呼び出し回数が $ 39,012,544 $ で $ 800 $ ms で間に合ったがそれ以上大きいと厳しそうである。 グリッドグラフのパスの数は辺が全てある場合は $ 5 \times 6 $ ぐらい、つまり $ 30 $ マスぐらいが愚直の限界と覚えておこう。 当然枝刈りをすればもっと速くなるだろうが、話が面倒になるので一旦ここで区切りたい。

大学につく。いつものケイジャンビーフのチー牛メシを食べる。いつも通りゼミが始まる。 後輩のスライドがしっかりと作り込まれていて、真面目だな〜と思うなど活動は多岐にわたる。

ゼミが終わった後は、先週の分の週記を投稿した。 そして作業に戻る。途中で典型のジャッジが来たので通しておいた。6ms だった。流石に軽いね。

大学を出て、ゲーセンに向かう。最近ゲーセンに向かいすぎである。 周りの人が上手すぎて頻度を上げないと拮抗する実力を維持できないのだ…。

f:id:spider_0859:20210622003103j:plain:w250f:id:spider_0859:20210622003114j:plain:w250
本日の成果。XROSS INFECTION と Verse IV 終わりそう。

足繫くゲーセンに通っている成果が出ているのか高難易度でのいいリザルトが最近は見られる。 5 月ぐらいに最終更新の PUC 難易度表では、上のそれぞれの曲の PUC 人数は $ 71 $ 人と $ 33 $ 人だそうだ。右の方をちゃんと PUC だせば地域ランカーぐらいは名乗ってもいいかい?ちなみに自分が既に出している 19PUC は $ 86 $ 人のと $ 91 $ 人のだ。 maimai とかいうゲームを真剣にやってた頃は 30 人目代の理論値 AP とかランクイン曲を複数持っていた気がするので、まだその域にすら相対的に達していないと思うと気が遠くなる。

家に帰ってご飯を食べる。夜に帰ってもご飯があるのは有難い。 今辛うじて競プロにつなぎ留められているのは Streak のおかげなので切らさないようにしてから寝ることした。 よく見たらついに前回の Streak を越している!

f:id:spider_0859:20210622005642p:plain:w400
前回の Streak の記録は 41 だったが越えた。絶対に切りたくない。

ジャンプは…眠いし明日読むことにした。

06/22 (TUE)

10:30 ぐらいに起床。濃い緑茶をやめてから胃の調子がそこそこ良い。

ジャンプを読んだ。田村隆平の最新作「灼熱のニライカナイが終わっていた。 最近のジャンプ、前作が売れた作家がコケまくっていてなかなか(業界の)厳しさを感じる。

気づけばジャンプ惰性購入記に入ってしまっている。週 250 円とかなので全然買い続けるんだけど、今真剣に楽しみだなぁと思っている漫画はヒロアカぐらいで、他もちゃんと読んでいるのだが週ごとに状況を確認するレベル。 漫画アプリの漫画の方が続きが気になるとかいう最悪の状態に陥っている。今は我慢の時期っぽい。伊達に中2 からジャンプを買い続けていないぞ俺はつってる。

今日の典型を確認する。★5。

https://atcoder.jp/contests/typical90/tasks/typical90_bu

問題概要。$ N $ 頂点からなる木が与えられる。各頂点には ab のラベルが与えられていて、各連結成分が両方のラベルの頂点を含むような辺の切り方をしたい。切る辺集合の数を数え上げろ、という問題。

制約が $ N \leq 10^{5} $ なのを確認。条件を満たすように木を切っていくなんて問題は木 DP と相場が決まっている。その方向性で考えると、必要な情報はある頂点を根とする部分木に対して、a しか持っていない・b しか持っていない・両方持っているの $ 3 $ つの切り方の場合の数だとわかる。 状態数が抑えられていい感じだが、最後に枝のマージを考える。 マージ先の頂点のラベル( $ c $ とする)は必ず持つことになるため、実質 $ 2 $ 通りを考えれば良い(両方持っている場合と $ c $ だけ持っている場合)。 $ c $ だけ持っている場合の数は、全ての枝の $ c $ だけ持っている場合の数 + 両方持っている(けどその枝は切る)場合の数の総乗となる。余事象によって両方持っている場合の数は求められるので結果的に $ O(N) $ の木 DP ができる。

★5 にしては面倒だなと思いつつも、まあ見た目からして木 DP だしマージぐらいしか考えることがないのでそんなものか。

昼飯を食べてからは、母親がドラゴン桜をみていたのでのぞき見した。

ドラゴン桜自体は面白いと思うのだが、このツイートと画像がチラついて困るという問題がある。 ファミリーマートのマークを雑にくっつけているのもかなり好きだ。

そのあとはいつもと同様にピアノをしばいていた。大分つらい部分を練習していたのだが、だんだん慣れてきた。 この調子で今月中には形にしないとなぁと思っている。 記録として YouTube にピアノ動画を up することも時々考えているのだが、なんか恥ずかしい(演奏者にあるまじき発言)ので断念している。

夕食。おいしかった。 夕食後はもこうの動画を見ていた。 ポケモン動画で負けフラグ立てて台パンするもこうみると、変わらぬ実家みたいな安心感と笑いが得られる。 ポケモンで発狂するもこうはまあもうお馴染みなのだが、時々 DS とかの昔めのゲームをプレイしてる。 やわらかあたま塾をプレイするもこうの動画が最高に面白かった。 最初のつみきを数えるゲームでルール理解してなくて沼プレイしている時、呼吸困難にさせられてしまった。 妙にうまくて澄ました実況よりこういうのを求めてるんだよなぁ。

www.youtube.com

Streak のための虚無を一応解く。B - アキレスと亀を解いたのだが、アキレスと亀に思いを馳せることができて、いい問題な気がした。 アキレスと亀の問題は両者が等速運動をしているなら極限という概念の暴力によって解決するの初見はかなりスッキリした覚えがある。 等速運動しないケースを問題にしたらかなりダルそうだなと思うなどしていた。

次にC - 正直者の高橋くんも解いた。 無向グラフと頂点 $ A,B $ が与えられて $ A $ から $ B $ への最短経路数を求めよと言う問題だった。 制約が $ N \leq 100, \quad M \leq 200 $ とかだったので、ベルマンフォードっぽい更新で求めた。$ O(NM) $ である。 解説を見ると、最短経路木を作ってやれば、木に含まれない辺も有向にできて DAG になるので $ O(N+M) $ になると書いてある。 最短路 DAG はちゃんと頭に入れておこうと思いつつも、「なら $ N,M \leq 10^{5} $ とかで出してくれよ」とか思ってしまった。

典型のジャッジが来ないので明日出すことにして寝た。

06/23 (WED)

9:45 起床。今日は大切な用事もあるしピアノもあるので最低限の時間には起きた。 昨日の典型を提出する。問題なく通る。★5 にしては難しかったな~と思ったので一応想定解を確認する。 完璧に同じ木 DP だった。これをもっと早く書けるようにしようと思った。

今日の典型を確認する。★6 だ。

https://atcoder.jp/contests/typical90/tasks/typical90_bv

問題概要。a b c の $ 3 $ 種類の文字からなる文字列 $ S $ が与えられる。この文字列に対して、次の操作が行える。

  • a 以外の文字を選んでアルファベット順で $ 1 $ つ前の文字にする。その後左側の文字を全て"変化"させる
  • "変化" とは a→b, b→c, c→a のように文字を変換することである。

文字列 $ S $ に対して行える操作の回数の最大を答えよ、という問題。

$ |S| \leq 60 $ であることを確認する。とは言え、このぐらいの大きさの制約が一番情報量がない。 なぜなら、こういう制約のときは愚直を却下したいだけのパターンと、四乗ぐらいのアルゴリズムを想定する場合があるからだ。 というわけで冷静に問題を観察する。全て a になってしまったら操作をすることはできなくなる。大まかな操作可能回数として $ a=0, b=1, c=2 $ と置いてみる。変化に関しては $ 2 $ を $ 0 $ にしてしまう処理であることに気づく。これを出来るだけ避けたい気持ちになると、非 $ 0 $ の最左要素を選択して操作を行い続ければ $ 2 $ が $ 0 $ に変化することないと割とすぐわかる。最初これを実装して TLE を食らい我に返った。"0001" の操作回数は $ 8 $ であるように $ 2 $ のべき乗を係数として操作回数を効率的に求められるのでこれにより、$ O(|S|) $ で解くことができた。

今日はジャッジがかなり早くきたのでとっとと AC した。

わりとすぐわかる最適な貪欲手順があって、それをそのままやると間に合わないので効率よく貪欲と同じことをするみたいな問題はしばしば出題されて、自分は苦手なので学びになった。

今日の用事のために既存のスライドを弄っておく必要があったので、コピーしてちょっと弄るなどした。 スライド作成って全然やる気が起きないのはなんでだろう。 多分もうスライドを作成できる段階になっていたら、既にその内容は頭の中では完結しているからかもしれない。

昼飯を食べてから、ピアノのウォーミングアップ兼練習をする。 うーん本当に今月中にものにできるか心配になってきた。先週の惨状よりマシなので今週はこれで許してもらおう。 自転車がパンクしているため、走って教室に向かうハメになる。というか、うちの自転車頻繁にパンクしている。 だれか棘とか刺してないか?これ。

ピアノから帰ってくると大事な用事の時間になる。 多分これはマジで喋っちゃいけない奴なのでふんわりと大事な用事と言っておく。 18:00 ぐらいに終わった。実りのある内容だった気がする。やることが明確化されたが、言い直せばやることが増えたぜ。

休憩がてら、クラッカーに Kiri クリームチーズを付けて食べる。 これ本気でうまいのでお勧めする。クラッカーが家にあるとか、安く売っているとかだったら試してみてほしい。 この方法で俺は幾度となくクラッカーを箱ごと消した

f:id:spider_0859:20210624003920p:plain:w300
Kiri クリームチーズ。こいつをクラッカーにつけて食べるとクラッカーが消える。

休憩後、長らく色々あってなかなかまとまって動けなかったインターンのタスクを改めて消化しなおす。 というのも前回の稼働から大分時間が経っていて何をやっていたのか忘れていたので自分のコードを読みながら作業を追っていた。 過去の自分が聡明だった(レアケース)ので、コードにコメントが残っていて読みやすかった。

食後、作業を続行する。この時間はよく兄が部屋に乱入してくるのだが、例にもれず乱入してきた。 面白いことを言って笑わせてくることもあるが、今日はイマイチネタが伝わってこなかった。 作業の結果、意味不明なものが錬成され、多分これは自分のせいじゃないので slack に投げて本日の営業を終了した。

この後、研究や競技プログラミングをしようかと思ったが乗り気じゃなかったので Twitter 閲覧などをしていた。 すると tolt_santyoku が BMS を 1 時間ぐらい配信するというので、見ることにした。 勝手に人の配信で認識のリハビリをしたり、セイウチくんに癒されてるうちに 1 時間が経った。

明日は普通に大学に行くので今日の分の週記をつけて、就寝を決めた。

06/24 (THU)

8:50 起床。ぼやぼやしながらやることを処理していた。 ちょっとして、今日の典型を確認する。★3。

https://atcoder.jp/contests/typical90/tasks/typical90_bw

問題概要。正整数 $ x $ がある時に、これを叩くと $ ab=x, \quad a \geq 2, \quad b \geq 2 $ を満たすような $ 2 $ つの整数 $ a, b $ に分裂する。 最初箱の中に正整数 $ N $ が入っていて、箱の中の整数は $ 1 $ 回の操作で同時に叩くことができる。箱の中の整数を素数にするのに必要な最小の操作数を答えよ、という問題。

流石に見たまんま。箱の中の整数が全て素数になっている状態は素因数分解で一意、なるべく素因数を均等になるように分裂させると二分木のような構造になる。 よって、完全二分木の葉の個数が素因数の数以上になる最小の高さ $ k $ を求めればよい。素因数分解ボトルネックになり、試し割りで $ O(\sqrt{N}) $ で解ける。

家に長い時間いた気がするが、大学に向かう。 とは言っても先日の MTG によって、結構方針転換したばかりで大学に行ってどうというわけでもないが、家族以外の人間の居る環境に行くためも大学には行くことにしている。

大学の最寄り駅に着いたのが結構遅く、キッチンカーで今から食べるのも渋くなったので First Kitchen で昼食をとることにした。 今週はちゃんとチー牛だなと把握しながらチーズベーコンエッグバーガーを頼んだ。美味しかった。

大学に着く。最初は作業しようとするも調べものや論文読みみたいなことをしなきゃいけないので、もぞもぞしていた。 調べものフェーズが苦手すぎるし、研究に向いているのか向いていないのか段々わからなくなってきた。

もぞもぞしていると、研究室の同期が paiza のページを開いていたので、自分も登録してやってみることにした。 paiza の仕組みがイマイチわかっていないのだが、同期に教えてもらいながらやった。 競技プログラミングの問題を解いていくと paiza がどんどん軽率に褒めてくれるのでうれしくなった。

途中で教授との MTG とかがある。まあ、上記の通り特に新しいことはなく調査フェーズだ。

paiza をやって気持ちよくなっていると、先輩が来て過去にコーディングテストか何かで解けなかったらしき問題を、解けないかと聞かれた。 制約はイマイチ覚えていないらしいが、興味深そうな問題なので掲載しておく。 因みに僕はまだ考え中です。自分のより速い解法があったら教えてください。

問題文

$ 1 $ から $ N $ の番号の付けられた $ N $ 本の木が生えています。 それぞれの木には $ m_i \quad (1 \leq i \leq N) $ 枚の葉が付いています。 $ 1 $ 日に、それぞれの木から $ L $ % の葉が落ちてしまいます。 正確には、その日の始めに $ X $ 枚の葉がついている木から $ \left \lfloor X \cdot \frac{L}{100} \right \rfloor $ 枚の葉が落ちます。

この時、$ K $ 日後にはそれぞれの木には何枚の葉が付いているでしょうか。

ただし入力は全て整数とする。

解法

$ O(NK) $ で愚直に割って引いてを実行することができる。まあこれは流石にわかる。

次に愚直改良として、$ L $ が整数なことを利用して $ K $ が大きくても速くできるのではないかと考えた。

10^18 * 0.99^x < 100 - Wolfram|Alpha

を見ると、$ m_i $ が $ 10^{18} $ であったとしても実数で考えると $ x = 3665.68 $ ぐらいで収束することがわかる。 そのため日数経過によって葉の枚数が変化しなくなったら打ち切ることで一気に速くなる。 $ 1 \leq N \leq 10^{4} $ ぐらいまでなら $ 1 \leq K \leq 10^{18} $ とかにも対応できそう。 現実問題、$ m_i $ は $ K $ と掛け算をするため良識があるなら $ 10^{16} $ とかにするだろう。(まあ大して変わらないけど)

うーんこれ以上はわからん。これでファイナルアンサーなら ABC の C や D あたりに置かれそうだ。

さて、paiza をやっていると S ランクになる。スーパーエンジニアだって。そんなに褒められると照れる。 べた褒めしてくれる paiza くんのことが大好きになった。 記念に S ランクの問題を解く。paiza は問題言及ができないので詳しい情報は省きます。 なんと TLE を食らう。確かに軽率な $ \log $ を付けた自覚があるが、軽率な $ \log $ を付けたぐらいで落ちる問題はクソや。 しかもこれ提出が一回までしか許されないのも知らなかった。ボケカス。paiza はクソや。 現場からは以上です。

今日は所属している音ゲーサークルの総会があるらしいので、早めに帰宅する。 マジで今日ちょろっと調べた以外は全て paiza くんに振り回されただけだった気がするが、気にしないことにした。

帰宅。総会の時間にはなんとか間に合ったので zoom を起動して接続。 若者が多い。 $ 4 $ 年前は自分もその立ち位置だったのかと思うと感慨深い。 大学に入ってから時間の流れが速く感じているが、中1 が 高2 になる時間が経過していると考えると長い時間を大学で過ごしているな。

総会の後は多くの人は zoom に残ってわちゃわちゃ会話に花を咲かせるのだが、楽しくて夜中まで通話していた。 友人がナスのアバターみたいなのにしてたり、よくわからない生物になったりしていてウケた。人生が $ 2 $ つあったら一回オンラインゼミ中にアレになってみたい。 適当にやっていた、ボルテの譜面クイズも楽しかった。音ゲーサークルみを久々に感じた。

06/25 (FRI)

11:11 起床。ゾロ目を狙って起床した。 いつも夜中に起きているのだが、通話はなんだかんだ疲れるのかしっかり寝坊する。

とりあえず今日の典型を確認する。★3。

https://atcoder.jp/contests/typical90/tasks/typical90_bx

問題概要。ホールケーキがあって、半径に $ N $ 箇所切れ込みが入っていて $ N $ 切れに分割されている。 時計回りに $ i $ 番目に分割されたケーキの大きさは $ A_i $ である。 連続するケーキを、合計の大きさが全体のちょうど $ 10 $ 分の $ 1 $ の大きさになるような選び方は何通りか答えよ、という問題。

よくある奴だ。見た目は完全に尺とりなのだが、円環上の問題なので列を $ 2 $ 倍加して尺取りをすればいい。 コンテスト本番なら惜しみなく二分探索をしてしまうだろう。

さて、ちょっと論文を読んだり昼ごはんを食べたりしている内に TA の時間になる。 先週は久しぶりにちゃんと質問がきて答えたのだが、今週はまた質問 0 に逆戻りした。 TA が終わるとすぐゼミ。ふむふむ。ほーん。ゼミはなんだかんだ初めて知る知見も多く面白い。自分が発表の回はつまらん。

すべてが終わって、用事を処理していたりしたらもう夜になる。金曜嫌い。 今日は TopCoder SRM があるのでぱっぱと夕飯を食べてパソコンの前に構える。

Easy。$ N $ 問の問題がコンテストに提案されて、 $ N \times N $ 行列 $ A $ が与えられる。 $ i $ 問目と $ j $ 問目の関係について、「 $ A _ {i,j} - A _ {j,i} $ だけ $ i $ が直接的に優位である」と定義される。 また、$ i,j,k $ について $ i $ が $ k $ に $ X $ だけ(直接・論証的)優位で $ k $ が $ j $ に $ Y $ だけ(直接・論証的)優位なとき、 「 $ i $ は $ j $ に $ \min(X,Y) $ だけ論証的に優位である」と定義される。 $ i $ の $ j $ に対する論証的な強さは、論証的優位な値の最大であり、 $ S(i,j) $ と表現される。 $ S(i,j) \geq S(j,i) $ の時問題 $ j $ より $ i $ を優先的に選出するとすると、他のすべての問題に対して優先的に選出される問題を全列挙せよ、という問題。

読みにくかった。$ N \leq 200 $ なので、正直どうとでもなりそうだが、グラフに落としてベルマンフォードっぽく更新して $ S(i,j) $ を求めた。 ワーシャルフロイド法の方が楽だったらしい。

Med。$ 2^{a} \times 3^{b} \times 5^{c} \times 7^{d} \times 11^{e} $ で表現される $ M $ が与えられる。 $ a,b,c,d,e $ の中央値を $ m $ として、以下の操作の果てに任意の $ M $ を $ 47^{m} $ にしたい。

  • リストとして、分数が並んでいる
  • 左から見ていって、一番最初に掛けたら整数になる分数を掛けて一番左に戻る
  • 掛けて整数になる分数がなかったら、そこで操作終了

有限操作、ステップ数が $ 3000 $ 以下、分数の数 $ 99 $ 以下…その他細かい制約を守って要件を満たす分数のリストを構築せよ、という問題。 とっかかりがなく悩む。 ちょっとすると、分母を $ 2^{5} $ 通り全て使うことを考える。冷静になると、$ 3 $ つ以上の素因数の積で割れる回数が $ m $ である。 よって分母の構成素因数の数の降順に分数を並べ、 $ 3 $ つ以上の素因数の積の分母を上には $ 47 $ を乗せ、それ以外には $ 1 $ を乗せれば良い。 面白いな、これ。しかし sample が通らない。通らない。通らない…。一生ここで躓きタイムアップ。

オチはこちら

さよなら…。制約は冷静に確認しような!

そのあと Codeforces もやる。Div.1 がんばるぞ~。

A: よく覚えてないし、大した証明もせずに通した。

B: わからなかった。助けてくれ。

そんなわけで冷えました。見ての通り気力も残らなかった。就寝。

06/26 (SAT)

11:00 起床。土曜だしこの時間でもいいかな。 とは言え、今日はサークル関係の大切な会議がある。 昨日の CodeforcesSRM の復習がちらつきながら典型を確認。

https://atcoder.jp/contests/typical90/tasks/typical90_by

問題概要。$ N $ 台の飛行機があって、最初 $ (AX_i, AY_i) $ にいる。それぞれの飛行機はグリッドグラフの $ 8 $ 近傍のどの向きかに $ 1 $ 秒ごとに移動する。 飛行機の向きは途中で変わらない。 $ T $ 秒後に $ (BX_i, BY_i) $ の位置に飛行機が存在するという報告があったので、これに矛盾しないそれぞれの飛行機の向きを答えよ。 適切な向きの組み合わせがない場合はそれを報告せよ、という問題。

$ N \leq 20000 $ とそれなりに大きい。当然 $ O(8^{N}) $ なんてかけられない。 $ (AX_i, AY_i) $ について $ 8 $ 方向を探索して $ B $ のどの飛行機と対応する可能性があるかは計算できる。 スンと冷静になると、完全マッチングの復元問題だとわかる。Dinic 法は全ての辺の容量が $ 1 $ なら $ O(|E| ^ {\frac{3}{2}}) $ とかだった気がするな。 なら通るな。でも結構 TL 怪しそうだしどうだろうと思っていた。まあ神を信じて解けたことにした。

昼飯はカレーを食べる。完全によそう皿を間違えて、 $ 3~4 $ かわり食べた。

昼食を終えるとサークル関係の会議の時間になるので、これを開始。 いい感じに決まっていた気がする。うん。17:00 ぐらいには終わっていたかな。 そこから昨日の Codeforces の B の続きを考えたりしていた。難しい~。

わからないのでダラダラして、夕食はマックを食べた。トリプルチーズバーガーうますぎて震えた。 AtCoder Beginner Contest 207 - AtCoder に臨む。

A: $ 3 $ つの数字から $ 2 $ つ選んだ時の最大値。ヤバい人なのでソートした。

B: 水色のボールが $ A $ 個入っていて、$ 1 $ 回の操作で 水色のボールと赤色のボールをそれぞれ $ B, \quad C $ 個入れる。 水色のボールが赤色のボールの $ D $ 倍以下の個数になるのに必要な操作回数の最小を答えよ、という問題。 $ A + Bx \leq CD x $ を満たす最小の $ x $ を求める問題。$ A $ は自然数なので、$ B < CD $ でないと絶対に式を満たすことはない。 後は式を整理して $ x \geq \left \lceil \frac{A}{CD-B} \right \rceil $ となれば解けている。

C: 開区間・半開区間・閉区間がすべてのパターンを混ぜて $ N $ 個与えられる。共通部分を持つ組み合わせの数を求めよという問題。 $ N \leq 2000 $ なので全ての組み合わせについて考える。区間の端を全て $ 2 $ 倍してやって、 開いてるなら左端は $ +1 $ 、右端は $ -1 $ してやることで閉区間と同様に扱える。あとは閉区間の共通部分判定。

D: 本日の発狂問題。二次元平面上の点群が与えられて、それ全部に対して平行移動と原点中心の回転が自由に行える。目標の点群があるのでこれに一致させられるか判定せよ、という問題。 $ N \leq 100 $ なので色々できるが発狂していた。点群は重心をとると回転では不変、平行移動では同じ分だけ移動する重心を基準にした座標を取ることで平行移動を完全に無視できる。 これは Big Bang とかいう問題で学んだな。というかあの時はちゃんと自分で思いついた気がするが。 あとは適当な元の点と目標点の偏角を回転によって一致させる。点群同士が一致しているかチェックすれば OK。 ここでハマっていた。まず回転によって一致させるプログラムがいかれていた。$ \cos $ を内積から求めたはいいが $ sin $ を求めるとき $ sqrt $ をかけ忘れる。 また、さらに $ eps $ の設定が悪かったせいで誤差落ちもする。もう散々や。E から先にやって本当によかった。

E: 順当にそこそこ難しい。長さ $ N $ の配列が与えられて、任意の連続部分列に切り分ける。 左から $ i $ 番目の部分列の和は $ i $ の倍数である必要があるとき、分割方法は何通りあるか、という問題。

シンプルでいいな。$ dp[i][j][k]: $ $ i $ までみた $ j $ 分割目の和 $ k \quad (\bmod j) $ の場合の数とすると解けそう。 $ O(N^{3}) $ になってしまって $ N \leq 3000 $ では間に合わない。最後の情報は正直微妙なので消せる可能性を疑う。 $ k=0 $ の状態どうしで遷移すれば次元が落とせる。しかし単純に個の遷移をしてしまうと結局 $ O(N) $ 遷移で計算量は変わらなくなる。 そこで DP の遷移高速化のテクの一つである、最左の遷移可能状態のみに遷移するというのをやる。 実際、同じ分割内で $ k=0 $ 同士の遷移を何度もすることと、$ k=0 $ の遷移一回で次の分割に向かうことは等価。 丁寧に遷移を実装すると通る。

F: D にハマってて読んだだけ。また考えます。

D にハマった割には成績は悪くなかった気がする。ABC で冷えることはよほどでない限り、まあなさそう。 明日は AGC なので震えています。しかし辞退するようでは、黄色に復帰してからが伸びないのでちゃんと出ます。

深夜に典型問題を通した。1000ms とかでブルブル震えていた。

06/27 (SUN)

11:00 起床。昨日の典型の解法を確認する。 昨日の典型はやっぱり Dinic 法で問題なかったようだ。Ford-Fulkerson を落とすための厳しい制約だったそうだ。

朝食後は作業したり、漫画アプリを閲覧をしたりしていた。 本日は昼食兄と自分しかいないので、昼飯をなんとかしなければならないのだが、起きていないので起こす。

昼飯は里のうどん。カレーうどんを毎回食べている。具が充実していて、満足度が高い。

f:id:spider_0859:20210628163334j:plain:w300
里のカレーうどん。どろっどろのやつで具も充実していて良い。

ゲーセンに行こうかという話も持ち上がったが、普通に混んでそうだしやることもあるので断念。

帰ってからは最近のコンテストの復習とかをしていた。 昨日の F 問題を解いた。D で発狂していたから気づかなかったが F も個人的にはなかなか辛かった。 木 DP のマージ部分が苦行になってしまっていた。

お馬さんレース(宝塚記念)を見る。よくわからないのだが、兄が最近よく見ているので一緒に見た。 自分もちゃんと勉強してお馬さんレースを見たいな。

そうして、お馬さんレースを見終わったら作業や競プロをした。 夕食後、AtCoder Grand Contest 054 - AtCoder をやる。

A: 文字列 $ S $ が与えられて、左端と右端の文字が異なる segment を消去する操作を任意回数行える。この時文字列を空にするのに必要な最小の操作回数を求めよ、という問題。 $ S $ 自体の最初と最後が一致しなければ自明に $ 1 $ になる。一致していても、途中に非頭文字の文字が $ 2 $ 連続以上で並ぶと $ 2 $ を達成する。 他の場合を考えると、頭文字が交互に出現する文字列になる。これは空にできないことが数学的帰納法でわかるので、$ -1 $ ということになる。AC。

B: 数列 $ A $ が与えられる。$ A $ を並べ替えたのち、左から数字を $ 2 $ 人で取っていく。 $ 1 $ 人目のとった数字の和が $ 2 $ 人目のとった数字の和以下の時、$ 1 $ 人目が数字を取り、そうでない場合は $ 2 $ 人目が取る。 最終的に $ 2 $ 人の取った数字の和が等しくなるような $ A $ の並びの数を数え上げよ、という問題。 数え上げ.pdf を信じているので「順列の数え上げは挿入ソート」を復唱していた。 実際に小さい順に挿入することを考えると、挿入した後ろの数字を取る人が変わるというなんとも言えない性質が出る。 永遠に沼っていた。実際は挿入 DP では解けない。

C: 長さ $ N $ の数列 $ A $ が与えられて、それぞれの要素の左側にその要素より大きい数字がいくつあるかを考えた時($ x_i $ などとしておく)に、その値が $ K $ 以下に収まる数列が与えられる。 これは、この条件を満たすように元の数列に対して(最小回数の)隣接 swap を繰り返した後と考える時、元の数列としてあり得る場合の数を答えよ、という問題。 $ 1 $ 個前の状態としてふさわしいのは前より $ \sum _ {i=0} ^ {N-1} \max(0, x_i - K) $ の値が $ 1 $ 大きくなるような swap をして得られる並び。 というのもこの値は一回の swap ごとに高々 $ \pm 1 $ される。具体的には $ A_i < A _ {i+1} $ のような隣接要素を swap すると $ x_i $ が $ +1 $ される。 つまり、$ x_i \geq K $ の場所を見つけて $ +1 $ する操作は行える。詰めると、動かせる要素の場所候補の数をかけるといいことに気づく。AC。

結果は AC 二完。苦しすぎ。B が解けなかったの悲しいね。 地力の足りなさ(精進の足りなさ)を嘆きながら今週を終えることになった。

週記(2021/06/14-2021/06/20)

06/14 (MON)

8:00 起床、スライドをやや直す。

朝食をたべる。鳩サブレ―を食べた。鳩サブレ―って言って通じるかな。

f:id:spider_0859:20210614223211p:plain:w300
鳩サブレ―はこんなの、多分地元のお菓子

夜暑くて身体ベタベタしがちなのでシャワーを浴びるなどしていた。 どうやら、外では雨が降っているらしいことに気が付く。 かなり嫌だが今日は必ず大学に行く日なので参った。とりあえず、家で少しダラダラすることにした。

雨がやんで晴れてきたので大学に向かう。 大学につくとちょうど 12:00 ぐらいでキッチンカーに直行する。 伝家の宝刀ケイジャンビーフチーズステーキ&ライスを今週も頼む。 なんなら合わせて飲む飲み物も毎週モンスターエナジーで固定化されつつある。

胃が悪い日だったため、チー牛飯がかなり堪える。しかも今日はゼミ輪講の当番の日だったのでかなり嫌だった。 ゼミでもう一人の人の発表中に、斜めになりながら画面を見ていたら、 研究室の秘書さんに「難しい内容ですか?」と聞かれたので「胃が悪くてナナメってるだけです」と答えた。 多分今週で一番かっこ悪い瞬間が記録されたと思う。

自分の発表をする。今回はそこそこ読みやすくて発表もしやすい論文を選んだ。 今回は B4 にもわかってもらいたいな~と思ったので結構丁寧にスライドを作成した。 とはいえ M1 以上は英語でスライドを作成することが義務づけられているため B4 がわざわざ読んでくれるか怪しい。 オンラインのゼミで発表するの、B4 の時は周りのリアクションがなさ過ぎて本当に何かの罰ゲームに感じたのだがもう最近は気にならなくなったな。 今の俺なら平常時のテンションで配信もできると思った。

発表中にアクシデントがあってつらかった。今回初めて zoom 共有で発表者用のカンペを表示するやつを試してみたのだが、Google Chrome を最新版に更新していないと存在するバグで、スライドを切り替えたときに前のスライドの下部が消えずに残留して共有画面が破壊されてしまうというものだった。 発表している自分の画面は全然普通なので気づかなかったが、大学にきている先輩に見せてもらったら本当に酷かった。草。というか普通にカンペ見れなくて焦った。英語のスライドだから、カンペないと現在位置を見失いがちなので助けてほしい。

このことによって俺が Google Chrome のアップデートを全然していないアホ野郎だということが研究室中に知れ渡ってしまった。 セキュリティの観点もあるから更新はこまめにした方が良いよと教授に言われた。 うん。いや、頭ではわかってるんだけど、更新を先延ばしにしちゃう病気なんですよね、と心の中で言った。 教授に「〇〇くんはなんでも先延ばしにするタイプだよねw」って言われて早く人間になりたいと心から思った。

そんなこんなで胃が悪くてあまり作業が進まず、喋ったりしてて大学を出た。 帰り道、降りるべき駅を寝過ごすということを久々にやってしまった。

家に帰って夕食を食べる。寝過ごして遅れても安心して食べられる飯が提供される実家、良すぎる。 気を遣うこともあることにはあるけど、永遠に実家にいたいぜ。どうも子供部屋おじさんです。

昨日の ABC の E 問題について頑張って考えていたけど、ついに諦めた。 黄色ぴったりぐらいの難易度で自力で解くのを諦めた問題は久々だったのでかなり自信をなくした。

解説をいくつか見るが、条件違反をするとボーダーライン+1 の斜めの直線に触れるため、 この直線を基準にして線対称に経路を反転してくっつけると、ミラー先の始点からの経路と 1 対 1 で対応することがわかる。 結果的にその経路数を、違反を無視した経路数から引いてやれば求める場合の数になる。 いや、天才かよ。どうやらこれは最短経路数問題の典型の 1 つらしい。

06/15 (TUE)

9:00 起床。したのだが、二度寝を繰り返し結局 12:00 に起床した。顔面終了した。

朝食を食べることは諦めた。直接昼飯を食べる。 そぼろご飯うまし。

昼食を食べ終わってからは、ぷよぷよ最強リーグの YouTubeアーカイブを見ていた。

ぷよぷよ最強リーグ

この人達、人間を辞めすぎていて面白い。 個人的にクソウマいプレーヤーを見ているだけでも楽しめる。 というかぷよぷよという競技はかなり e-sports に向いているなと思う。 対人戦で、長い歴史で蓄積されてきたセオリーがありつつ、新しい戦い方を模索する人達もいて… などなど一言で表現することはできないが、もっと e-sports で騒がれてもいいようなゲームに見える。

それに比べると音ゲーはかなり e-sports 化苦しそうに見える。 自分は音ゲーが好きなので期待しているのだが…

さてひとしきり休んだところで、昨日解説を見た E 問題について再考する。 最短経路数問題について、「特定の斜め線を通る経路数を、線対称に移動した始点からの経路数と考えることができる」 という事実は、知っておいて損はない。しかし自分はこの手の特殊操作テクニックが苦手なのでなんとか別のアプローチでいけないものか考える。

ちなみに問題が $ K=0 $ で固定だった場合、カタラン数に一致することがわかる。 これは聞いたことがある。Wikipedia でカタラン数について調べたときに、カタラン数の実例みたいなものがいくつか挙げられていた。 しかし、よく考えるとカタラン数についてよくわからず、式しか知らない。 その導出方法が分かれば、E 問題をパズルチックに解く以外の方法に結び付くのではないかと考えて、勉強をすることを決意した。

上記のことを踏まえてE - White and Black Ballsの記事を書くことにした。

記事を書いている間に用事の時間が来た。 また、それが終わったらピアノを弾こうとしていたのでしばし中断となった。

今日取り組んだ箇所がマジで全然うまくならなくて閉口した。 先週にいらすとやの画像を貼ったメトロノームをかけっぱなしにして気が狂いそうになっていた。

さていつも通り夕食までピアノを弾き続けていた。夕食を食べる。

夕食後休憩を終えると、また勉強に戻る。 母関数によるカタラン数の導出、フィボナッチ数列の一般項の導出などを見る。感動する。 そもそも母関数周りを真面目に勉強したことがないため、勉強するかと言う感じ。

形式的冪級数とかも関わってくる領域なので、合わせて勉強しようとして色々調べているとあっという間に時間が過ぎていく。 そもそもフィボナッチ数の一般項を誤差なく求めたいと思ったりして mod sqrt を発見して感動するなど、 かなりわき道にそれた検索行為をしているためこうなってしまう… 目的のものだけを調べることってできなくないですか?俺に集中力がないのは認めるが、みんなそうだと思いたい。

06/16 (WED)

10:00 起床。そういえば書いたショートレポートを提出していなかったので起床即提出。

朝食を食べる。 水曜日はピアノなので練習していくことになるが、午前中はイマイチ練習できる状況にないので別の事をする。 E - White and Black Ballsの非天才的解法を模索しているが、依然として成果がない。 非天才的解法の模索がかなり面倒なことは、TL にも AtCoder のページにも誰も解説を上げていない時点で想像はできたが、かなり苦しい。

割と無駄な時間をすごしてしまったなと思いながら昼食の時間になる。 昼飯の後に、昨日父親がお土産に買ってきた CINNABON を家にいる人で食すことになる。 これは美味しいシナモンロールなのだが、昼食直後に食べるのは自分の胃の事情には厳しいものがあった。 とはいえ、シナモンロールはかなり賞味期限がすぐ来てしまうため、このタイミングで食べるしかなかったので食べた。 美味しいも苦しくなった。美味しかったのでいいか。

そんなことでピアノを練習して、レッスンに向かう。 今週も散々だった。というか、遠回しに早く曲を形にして来いと言われた。 反省しながら、帰り道はまた例の問題の非天才解法に思いを馳せていた。 競技プログラミング的には、最近出題された (Binary) Trie を自分のものを持っていない(これは本当にクソで反省をしています)ので、作るというタスクもあり、あまり ABC の復習に時間を使ってばかりもいられないなとも思った。

そもそもなんで例の問題の非天才解法が詰まらないかということをここに書いておく。

適当な例を下図に示す。 この図の太線部の交差点への太線を超えない経路数が出れば答えが出そうだ。 なぜなら余事象を考えると、初めて太線を越える位置を決めてやれば その場合の数は、$ 越える直前までの経路数 \times 越えた後からゴールまでの経路数 $ で求められて、後者は二項係数なので十分高速に求められるためだ。

f:id:spider_0859:20210620221739p:plain:w300
左下の始点から太線部上の交差点への太線を越えない経路数が知りたい

$ K=0 $ の場合に太線のラインの経路数を数列として観察をすると(漸化式を立てても良い)、カタラン数になっていることがわかる。これは嬉しい。解ける。

しかし、 $ K \neq 0 $ だとかなりつらい。漸化式すらうまいものが立てられないんだけど、どうしたものか… 漸化式さえ立ってくれればそれをなんとか処理できるのでいい感じの漸化式を立てたいな。

とまあ、全然思いつかないためやるべき作業をして脳をリセットすることにした。

作業後、全然わからないので困った。並行して調べている、形式的冪級数とかの話はシンプルに面白いのでそっちを読み進める方向で一日を閉じた。

6/17 (THU)

8:50 起床。もう一限の時間に登校するのは嫌になったのでこの時間に起床をしてしまっている。 ゆっくりめに登校することによって QoL が改善するのだから仕方がないだろう。

一度典型をやらない生活をしてしまうと、中々典型 90 をやる生活に戻すことが難しくなっている。 来週にはちゃんとそっちのリズムに戻していきたいと思う。

一方で、学校に到着する前にゲーセンに行くというリズムはすっかり出来上がっている。人間の欲望の力ってスゲー。

f:id:spider_0859:20210620224034j:plain:w300f:id:spider_0859:20210620224049j:plain:w300
行きがけのボルテはうまいらしい。20S の残りが 2 曲となった。

普通にボルテうまい。たまにはキッチンカー以外のものを食べようと思って First Kitchen で食べることにした。 頼んだメニューは チーズベーコンエッグバーガー のセットだ。 久々に来た First Kitchen のメニューにすらチー牛の匠としての影が見えるのウケる。 ちなみに本当に狙ってなくて、記事に書くときに気づいています。

そんなこんなで大学に着く。大学に着いたときに先週の週記で来週はタンドリーチキン丼の写真をブログに記録するとかなんとか書いていたことを思い出す。来週、来週こそはちゃんと記録する。

大学に着いて作業を進める。2 つの作業をなんとなく並行しているのだが、1 つの作業の進捗が芳しくないため、今日はもう一つの進捗を見える形にして、MTG に持っていくことにした。

教授と話して思いのほかちゃんと論文が書けそうな話にはなりそうな気が(勝手に)してきた。 関係ない話になるが、論文と言えばゼミで発表できそうな論文読み溜めストックがそろそろ切れた気がする。 まずいので、何本かまた読んでおかなきゃならない。 たまにゲボ程読みにくい論文もあって、そういう論文に当たると最悪で、ゼミで発表するのも大変だからである。 全部読んだ結果、そんなおもんなかった時ははったおしたくなる

なんだかんだ喋ったり作業したりして、研究室を出るのが 20:00 を過ぎていた気がする。 腹減ったという話になるも、緊急事態宣言中で飲食店が 20:00 に閉めてしまう。 しかし、そこは学生の街・日吉、自粛に応じない飲食店などそこそこあるだろうという張りをして先輩とひようら(日吉キャンパスの裏の街)を見て回ることにした。

正直、日吉をなめていた。日吉なら適当をやっている飲食店がそこそこあるという期待はかなりこっぴどく裏切られた。 マジで全然開いていない。ラーメン屋も大概はしまっているし、開いてそうな店もテイクアウトしかやっていない。 ただ一軒を除いて…。

がっ〇んとかいう店が普通に開けていて先輩と爆笑するも、死ぬほど並んでいるので流石に食うという感じにはならず、笑って帰路に着いた。というか通りのど真ん中の店なのに、すげぇ心臓だなと思った。

帰るとかなり疲れていて、元気は全然なかったのだが D - 動的計画法を解くことにした。

問題概要。下図のような DP テーブルを構成することを考える。具体的には下と左のマスの数字を足したものでマスを埋めていく。 ただし $ \bmod 10^{9}+7 $ で数字は表現される。 このテーブルで L 字に $ 3 $ つの領域の数字が与えられる。この領域が当てはまる場所(列・行)で、最も行が若く、列も若いものを求めよ、という問題。

f:id:spider_0859:20210620225843p:plain:w300

ちょっと観察するとすぐ二項係数テーブル最短経路数経路数テーブルであることがわかる(2021/06/22 修正)。というかアルゴリズムからもわかるだろう。

例えば下図のようなパーツが与えられていて、$ 15 $ の位置の数字を $ A $、$ 35 $ の位置の数字を $ B $、残り $ 1 $ を $ C $ とする。 すると、 $ B $ の左や、$ C $ の下の数字も求められる。それぞれ $ B - A $ と $ C - A $ だ。 こうすることで斜め $ 3 $ つのラインが求められたことになる。 この右肩下がりの斜め $ 3 $ つの数字はどれも $ r+c $ の値が同じだなあということに気づく。 というわけで二項係数の式にしてみる。当てはまる位置を $ (r,c) $ と置いている。

f:id:spider_0859:20210620230710p:plain:w180

$$ \begin{align} \binom{r+c}{r} &= \frac{(r+c)!}{r! c!} &= A \tag{1} \\ \binom{r+c}{r+1} &= \frac{(r+c)!}{(r+1)!(c-1)!} &= B \tag{2} \\ \binom{r+c}{r-1} &= \frac{(r+c)!}{(r-1)!(c+1)!} &= \tag{3} C \end{align} $$

となる。見るからに割り算で良い感じに打ち消せるため、$ (1) \div (2), \quad (1) \div (3) $ をする。 整理後の式を次に示す。

$$ \begin{align} (C - A)r - Ac = A - C \tag{4} \\ Ar + (A - B)c = B - A \tag{5} \end{align} $$

これらの式を連立させれば $ (r,c) $ が求まる。$ \bmod 10^{9}+7 $ で求まるため、大丈夫か考える。 問題文に行と列は $ 99,999,999 $ 以下であることが書いてあるため、一意。 よって出てきた $ (r,c) $ を出力すれば OK。

結構好きな問題だったので安眠。

6/18 (FRI)

11:30 とかに起床した気がする。最近寝つきが悪くなってきて、夏の到来を感じています。

読み始めよう読み始めようと思っていた、怪獣8号をついに読み始めることにした。 初回無料なので、一気読みが可能なため今まで自分にステイをかけていた。

昼飯をまたぎながら読んでいる。 半分ぐらいをゆっくり読んだ。自分は漫画を相当ゆっくり読むタチだと思う。 なぜなら、文字情報が少なくしっかり色んな情報をキャッチするのはテキストベースの物語ほど容易ではないためだ。 また、アニメのように勝手に流れてしまうということもないため心おきなくゆっくり読むことができる。

ゆっくり読みすぎた。ついでに他の木曜日更新の漫画とかも読んでいたりしたせいですっかり夕方になっていた。

しょうがないので(?)今日の典型をチラ見した。

https://atcoder.jp/contests/typical90/tasks/typical90_br

問題概要。$ N $ 個の二次元点が与えられて、二次元平面上の $ 1 $ 点を次の不便さが最小になるように選ぶ。

  • 不便さは $ N $ 個の点の選んだ点とのマンハッタン距離の総和

この時の不便さを求めよ、という問題。

う~ん、まあこれは見た瞬間 $ X,Y $ 座標がそれぞれ独立に考えられて、中央値を選ぶのが最適。 証明も簡単なのだが、これはもはや競技er の中では知識として定着していそう。

TL を眺めているとこれが線形でできるとのこと。単純な解法ではソートがボトルネックになって $ O(N \log N) $ だと思う。 よくよく記憶をたどると、数列の $ k $ 番目の数を選択するアルゴリズムであるところの Median of Medians の存在を思い出した。これを使えば確かに線形でできる。しかし面倒だし、実装したことないという理由で見送った(カス)。

夕食のあと、なんとなく胃がだるくてダウンしていた。Codeforces の時間まで休むことにした。 最近胃の調子が悪い一因として「濃い緑茶」みたいなのが家に沢山買われていてこれを飲んでいることがありそうだと思えてきた。胃の悪い人は麦茶でも飲んでいたほうがよさそう。

さて Codeforces (Div.2) をやる。これはもともと Div.3 用だったらしい。全完を狙いに行く。

Dashboard - Codeforces Round #726 (Div. 2) - Codeforces

A 問題。数列が与えられて、平均が $ 1 $ になるように末尾に非負整数を足す。何個足せばできるか、という問題。まあ数列の総和と長さ $ N $ を比較して、総和の方が大きければ $ 0 $ を足し続ければよく、それ以外なら足りない数字をそのまま足せばいい(同じなら答え $ 0 $ だが)。

B 問題。$ N \times M $ グリッドが与えられて、人が $ (i,j) $ にいる。$ 2 $ 個のヨーヨーをグリッド上に落とすと、人は最短ルートで $ 2 $ 個回収して元の位置に戻る。人の移動量を最大化するヨーヨーの落とし方を答えよ、という問題。グリッドの外周より大きく移動させることは不可能なのは自明。よく考えると隅に置くことで、これを達成することができる。ギャグだ…。

C 問題。長さ $ N $ の数列が $ A $ が与えられて、$ | A_0 - A _ {N - 1} | $ が最小になる並び方について考える。 このうち、$ A _ i \leq A _ {i+1} $ となるような $ i $ が最も多くなるような並び方を答えよ、という問題。 とりあえず、$ |A_0 - A _ {N-1}| $ が最小にするために $ A $ をソートする。 最小の差を見つけたら、実はその間で数列を $ 2 $ 分割して逆さにつっくけ直せば最適である。 こうすることで、$ |A_0 - A_{N-1}| $ は最小で、条件を満たす $ i $ の数も昇順より $ 1 $ しか損しない。 $ N=2 $ の時だけ、昇順にできるため例外処理を怠らない。

D 問題。整数 $ N $ が与えられて、 $ 2 $ 人がゲームをする。それぞれの人は自分のターンに現在の整数の $ 1 $ とそれ自体以外の正の約数を引くことができる。最初に操作ができなくなった人の負け。最適にゲームが進んだ時の勝敗を判定せよ、という問題。 $ N $ が $ 10^{9} $ と大きいので DP とかをするのは無理。Nim に容易に落ちたりすれば簡単なのだが、そうでもないので難しい。 観察をしていくと、どうやら奇数が回ってきたら負ける。理由は奇数が回ってきたら相手に偶数を返すことになり、その偶数に対しては直近で選ばれた約数がそのまま選べて、操作をすることが可能である。よっていつか素数に行きついて負ける。しかし偶数がいつでも勝てるというわけでもなく、$ 2 $ に行きつくと負けてしまう。$ 2 $ のべき乗以外の数字は上記の理由と同じように必ず操作を続けられるので、$ 2 $ のべき乗のみ例外として考えると、$ 2^{odd} $ は負けて、$ 2^{even} $ は勝つ。以上を整理すると AC。

E 問題。文字列 $ S $ が与えられる。これに以下の操作が行える。

  • 末尾の文字を消す。
  • 現在の $ S $ を末尾に連結する。

長さ $ K $ の作れる中で辞書順最小の文字列を求めよ、という問題。 $ S $ の prefix を見て、その prefix を無限に連結して最初の $ K $ 文字を取るので良いことがわかる。 これを愚直な文字列比較でやっても E1 の要求には応じることができる。$ O(NK) $ でできる。

しかし E2 では線形ぐらいでできることが期待される。 一文字ずつ左が見ていって最適な prefix を発見したい。

  • 頭文字より辞書順大きい文字が来たら打ち切り
  • 頭文字より辞書順小さい文字が来たら続行

は割と自明。同じのが来ると困るが、とりあえず続行して頭文字じゃなく一つ右の文字を基準にするとよい。 ただし、打ち切ったら基準をズラした分は戻ったところまでの prefix が best。 あとは、愚直解法と同じで連結をして $ K $ 文字だけ取り出す。 文字列の線形アルゴリズムは賢いなぁ…

F 問題。連結無向グラフが与えられる。また各頂点の最初の値と目標の値も与えられる。辺を選択して端点の値に整数 $ k $ を足すことができるとき、目標の値にできるか判定せよ、という問題。 見た感じよくある、DFS 木を取ってきて葉から構成していく問題に見える。 単純に葉から構成して根の値が目標に一致していれば YES と書く。WA。 冷静に考えると、無向 DFS 木を使っているのでなんか悪さをするとすると後退辺ぐらいしかない。後退辺は根へのパスのショートカットと考えられるので、深さの parity が異なる $ 2 $ 頂点をつないでいる場合、$ 2k $ を根の値に加算できる。このような後退辺がある場合は、根の値と目標の値の parity が一致しているか見る。なんとかコンテスト内 AC。

ギリギリ全完できていい気分だと思っていたらきよしくんが不穏なことを言っている。

え??俺 E 問題全然ケアをしていないんだけど大丈夫か?

ほう。試す。落ちる。よく自分のコードを見ると、最後まで基準をズラした状態で行ったときは打ち切りとみなして、ちゃんとズラした分を戻して prefix を取らなければならないのにやっていない。 結構このミスをしていた人は多いらしく、TL が阿鼻叫喚に(主観です)。

結局 E1,E2 同じコードを投げた僕は滅されました。うくく…。 F を通していたのでなぜかレーティングは上昇した。紫だと失敗してもレート上がるしよくわからない。

6/19 (SAT)

昨日の Codeforces の System Test が遅かったためかなりの夜更かしをしてしまった。 案の定 12:00 起床とか。

本日も朝飯を食べることを諦めた。 生活崩壊最高!(最低!)

土曜の典型は難しいのでチラッと見たけどまあぱっと見ただけでは解けないので割愛。

13:00 からは約束があり、高校同期と通話をしていた。

午後に活動をしようとする。一応活動はしたが、すぐ飽きる。 生産的な活動をすることを諦めてためている漫画を読むことにした。

怪獣8号の続きを読む。めちゃくちゃ王道で、いい漫画だと思う。 よく自分は逆張りオタクだと思われるんだけど、逆張りではなく流行に対してマイペースなだけなんだよね。 好きなものが流行ってたり、全然流行ってなかったりする。 この週記で話題にする漫画は流行っているものばかりだけど。

単行本発売ペースがかなり緩やかな Artiste という漫画の最新刊を読んだ。 これもかなり雰囲気が好きな漫画。 もちろんキャラクターも好きなんだけど、この漫画はかなり作品全体に流れる雰囲気がやさしくて好き。 あと、クロックムッシュっていう名前のネコが出てくるんだけどかわいい。

漫画の最新刊を途中まで読むと、以前までの刊を読み返したくなって結局以前の話を全て読み返してしまう。 特に単行本のペースがゆっくりな漫画はその傾向が強い。 新刊を読むたびに全てを読み返すため、既刊を $ N $ として $ O(N^{2}) $ かかるオンラインアルゴリズムとなっている。

さてぐだぐだしているうちに、夕食の時間になる。両親の結婚記念日なので、近所の行きつけのイタリア料理店のテイクアウトをしていた。 イタリア料理は好きだ。トマトが好きだし、何よりチーズたっぷりだからかも。この場合必ずしも牛要素がないからチー牛ではなさそう。

食後は胃の不調に苦しみながらも、AtCoder Beginner Contest 206(Sponsored by Panasonic) - AtCoderに出る。

A 問題。税抜きの金額が与えられるので、 $ 8 $ % の消費税を加味して $ 206 $ 円との比較をする問題。

B 問題。$ i $ 日目に $ i $ 円貯金して行った時に、何日目に $ N $ 円以上の金が貯まるかという問題。 $ i $ 日目の貯金総額は $ \frac{i(i+1)}{2} $ なので実は愚直に判定しても $ O(\sqrt{N}) $ で解ける。

C 問題。整数配列 $ A $ が与えられて、$ A_i \neq A_j $ かつ $ i < j $ の組を数え上げろという問題。 これは一億回ぐらい出題されていて、余事象を考えて等しい要素ごとにカウントをして、等しい要素同士の組を数え上げて全体から引く。 std::map とかを使うと楽。

D 問題。長さ $ N $ の整数列が与えられる。これを回分にするために、「ある数字を選んで、全てのその数字を別の単一の数字に変更する」という操作を任意回数行う。 最小の操作回数を求めよ、という問題。これかなり詰まったので反省。$ \lfloor \frac{N}{2} \rfloor $ 組の数字を最終的に等しくすることが目標になる。 複数の等号条件を推移など含めて表現をするために、グラフを使うのは典型ですね。 これをすると各連結成分に対して、その要素数 - 1 だけの操作回数がかかる。最初有向にして最長路の長さだと思ったんだけど、脳が壊れているだろ。

E 問題。むずすぎて泣いた。$ [L,R] $ に含まれる正整数 $ x,y $ で、$ g = \gcd(x,y) $ として、 $ g \neq 1, \quad \frac{x}{g} \neq 1, \quad \frac{y}{g} \neq 1 $ となるような $ (x,y) $ の組を数え上げよ、という問題。 見た瞬間 $ g $ を固定したくなって、$ \frac{x}{g} $ と $ \frac{y}{g} $ を $ x' $ や $ y' $ と置いて、全て $ g=1 $ と同じ問題を解きたくなる。 さらに、扱える整数の範囲も $ g $ の値によって $ [\frac{L}{g}, \frac{R}{g}] $ となるので $ y' $ を固定しても $ O(R \log R) $ で済む。 また、$ y' > x' $ として最後に $ 2 $ 倍しても問題がない。 ここからが全然つまらなかった。$ y' $ の値に対する $ x' $ の数を求めるのが難しかった。 最終的に苦し紛れに $ y' $ を素因数分解して素因数の数を $ L $ として $ O(2^{L}) $ の約数包除をした。 $ L $ が小さい(かつ最大ケースは非常に稀)ので間に合うことを祈った。通った。

F 問題。ここに来て F を通さないと冷える状況になってしまった。$ N $ 個の半開区間が与えられて、$ 2 $ 人でゲームをする。 それぞれの人は、自分のターンに現在選ばれている半開区間のどれにも overlap しない半開区間を選ぶことができる。 最終的に選ぶことができなくなった人の負けになる。最適時の勝敗判定をする問題。 $ N \neq 100 $ なので当然愚直は愚か集合を状態にもつような DP をすることも難しい。 焦っていたため、タイムアップの直前に区間 DP を思いつく。 具体的には、それぞれの人は高々 $ N $ 個の選択ができて、それぞれの残しの区間は $ 2 $ 分割される。 それぞれについて、同じ問題を解いた上で結果をマージすることで全ての遷移先を網羅できる。 ちょっと考えると、boolean ではダメで grundy 数を考えれば良い。結果的に $ O(N^{3}) $ で解ける。

DEF 問題、どれも自分の典型力や演習量が足りなかったなという感じで反省。 E 問題は特に苦手なのでちゃんと復習しておきたい。

6/20 (SUN)

12:00 起床。来週の目標は早起きです。

昼食を食べる。今日は父の日なので、事前に絞っていたプレゼント候補を決定して買いに行くことにした。 Mac 周辺機器にあたりをつけていたので家電量販店に向かう。

色々あって、購入が完了する。家電量販店でものを探すのってなんでこんなに大変なんだろう。 遊びたくなったのでゲーセンに行く。

写真をすっかり撮り忘れたが、XROSS INFECTION [GRV] の PUC が狙えるところまで持っていくことができたりした。 インペリアル 2 になったらボルテの頻度を少し減らすかもしれない。

帰って夕食。すき焼きだった。美味しかった〜。

さーて今日は早めの時間に Codeforces があった気がするので Codeforces を開くと Running って書いてあって声出た。 21:05 からだと思っていたんだけど、19:05 からだった。これ不可能だろ。

1 問易しめの問題を通してお茶を濁してから今週を終えることにした。

今週も全然競技プログラミングしてなかったな。来週からはちゃんと典型を処理したい。

週記(2021/06/7-2021/06/13)

06/07 (MON)

8:30 起床。大事な用事(オンライン)が 10:00 からあったので大学に行かず家で待機していた。 今日の典型を確認する。

https://atcoder.jp/contests/typical90/tasks/typical90_bh

問題概要。長さ $ N $ の数列 $ A $ が与えられて、その部分列を $ B $ で次の条件を満たすものを考える。( $ B $ の長さは $ M $ とする)

  • ある整数 $ K \quad ( 1 \leq K \leq M) $ が存在して次の $ 2 $ つの条件をともに満たす。
    • $ 1 \leq j < K $ に対して、 $ B_i < B_{i+1} $
    • $ K \leq j < M $ に対して、 $ B_i > B_{i+1} $

LIS っぽい見た目をしている。とりあえず左から見ていって最大値が $ A_i $ になる LIS を考える。 これは $ O(N \log N) $ で、次に右から見て最大値が $ A_i $ になる LIS が欲しくなる。 LIS の DP は $ O(1) $ で revert が可能なので、事前に右からの LIS は計算しておき順次 revert していけば欲しいものが得られそうだ。 でも★5 の典型で LIS の DP を revert するなんて問題が出るだろうか…と思ったが考えるのをやめた。 とはいえ、ABC で有名な DFS 中で LIS を revert する F - LIS on Tree が青 diff なことを考えると、やはり想定ではなさそうだ。

10:00 になり用事が始まる。そして終わる。 大学に向かう。

大学に着くともう昼食の時間なので、いつものようにケイジャンビーフチーズステーキ&ライスを頼む。 これ本当に美味しいので、なんかの用事で矢上キャンパスに月曜に来たら食べてほしい。

食べ終わって少しするとゼミの時間になる。こちらも割愛。 週記なのに割愛する部分が多すぎて涙がちょちょ切れるぜ。

ゼミが終わり、作業をする。楽しいパートに入っているのだが、やりたいこと自体は依然として難しいのでかなり困っていた。 一応最低限今週とるべきデータらしきものは取れた気がするので、一旦思考パートかもしれない。

思考につかれてきたので研究室内で平然と競プロを始める。 tester を頼まれていたので、それを考えるなどする。当然内容は言えない。 tester をやっていること自体はインターネット上から一応確認もできるはずなのでこれは言っていいはず、だよね? 解けたので writer に解けたから帰ったら実装すると報告する。

作業に戻る。なかなかうまくいかないので 18:00 ぐらいで切り上げてゲーセンに行って気分転換をする。 本日も 19 の 1 ERROR を出してしまい、人生の体現者となっている。 最近ボルテ上手いからここらで実力を伸ばしていきたいところなんだよな。

帰宅。飯を食べるも、胃にばくだんいわを $ 100 $ 発生させる結果となり本日の活動終了が決定した。 ベッドに横になりながら兄とみんはやをやったりして時間を過ごしていた。

11:40 ぐらいに今日の Streak をつないでいないことに気が付き、これが今の競技モチベの一つになっているので無理やりつないだ。 writer に申し訳ないと思いながらも活動不可能だったので翌日に実装は回すことにした。

典型未ACがたまっていることが気になったが、健康状態の面でしょうがないので就寝。

06/08 (TUE)

10:00 起床。典型を通してないので朝の TL を見ることが許されない。ついでに今日の典型も確認できないからつらい。 胃の調子は依然として最悪なので、朝食は抜くことにした。乳酸菌飲料を一本だけ飲んだ。

午前中の記憶があまりない。正午ぐらいから tester の実装をしていた。AC。 このタイミングで昼食の時間になる。母親が弁当を作っておいてくれたのでこれを食べればよい。感謝。

昼食を終える。

writer とやりとりをしていた。出題の日が楽しみ。俺も writer デビューしたいな。しようかな。

ピアノの練習をなかなかできていないの本当につらいなあと思って開始する。 結局夕食の直前まで弾いていた。 弾けないところを一生練習していると段々つらいのが気持ち良くなってくる。 完全に脳内物質が出ちゃってるんだよね。

今日の練習にはメトロノームを久々に使ってみた。最近使ってなくって埃っぽかった。 こいつは BPM を合わせると左右に振れてその BPM の四分でカチカチ音を鳴らしてくれる優れものだ。 あと地味にこの見た目も好き(いらすとやの画像を下に貼ってみた)。 如何に自分が拍を取れていないのかを実感させてくれた。 心なしか安定感が増したように思う。明日も頑張ろう。

f:id:spider_0859:20210608190242p:plain:w300
メトロノーム(いらすとや)

夕食の後、コンテスト予定表を見る。明日の 20:05 分から SRM らしい。完全に忘れていた。 流石に TopCoder で黄色になりたいな。 黄色と言えば今週中に色変記事を書こうかな。とは言え、自分が何をしてきたかなんて全然覚えていないな。

競技プログラミングの練習のために、忘れてそうな令和 ABC を再バチャした。最近ちょくちょくやろうとしている。

AtCoder Beginner Contest 128 - AtCoder

D 問題。制約が緩めで 4 重ループを書いた。こういう制約が緩くて方針がよくわかりにくい問題でワタワタしなくなったのは成長かな。

E 問題。これ普通に難しいぜ。まあ $ 1 $ つの工事に引っかかるかどうかの条件は $ [S_i - X_i, T_i - X_i) $ であることにはすぐ気づく。naive にやると、 $ O(NQ) $ なので工夫が必要だな…今回は双対セグ木を使って chmin クエリで $ Q $ 個のクエリの答えを更新していった。多分想定は $ X_i $ の小さい方から見ていって引っかかるクエリを除去していく、みたいなやつな気がする。

F 問題。地力で通せた初の橙 diff 問題だったこと以外の全てを忘れていた。なんか時間内に合わんかった。 最悪の気分になったが、今こそ記事にするべきだと思って記事を書くことを決意した。

本日の活動はここまでとなった。就寝。

06/09 (WED)

10:30 起床。微妙に起床が遅い日が続く。 典型を確認しようとするも、最近連日で典型の問題を見ていないため Twitter で典型を確認できないという悪循環に陥っている。

今日は週一でピアノに行く日なので、手ならしをしたいが寝起きはキツイのでちょっとしてからすることにした。 典型も見られないし、いい加減処理しておきたいなあといいつつ怠けていた(ここ今週の最悪ポイント)。

具体的には体調も気分もノっていなかったので漫画を読んでいた。 今週のジャンプを月曜に買ったのに読んでいなかったので読んでいた。 最近のジャンプは猛烈に次が気になる漫画がなくて困っている。 いや、ヒーローアカデミアと Dr. STONE は続きが結構きになるかも。 ただ、ハンターが連載している時期は、毎週次のハンターが読みたくて狂いそうになっていたのだが、そういう感覚はすっかりしなくなってしまったな。

うーん、あとは金色のガッシュを読みなおしているのだが、こちらは結構刺激的だ。 話の流れをある程度覚えていても面白い漫画は面白いなぁ。 今度ハンターを読み返そうかとも思ったが、休載期間を思って辛くなりそうなのでやめておくことにした。

そんなことを思っているうちに身体が目覚めてきたのでピアノを弾く。 日が高い時間に指を動かすのはどうも得意じゃないらしく、指がよく開かない。 指がよく開かないからこそ事前にウォーミングアップをするという側面もある。

昼食を食べて、稽古に向かう。 今日の稽古はダメすぎて引いた。もっとしっかり練習時間を確保しなければ死が待っているかもしれない。 凹みながら帰宅。

家に帰って作業をしようと思うも、なんかダメな感じだったので競プロすらせずに金色のガッシュを読んでいた。 今週はなかなかやる気を失うタイミングが多くて困った。

少しして、競プロ自作問題の考察をしてメモったりしていた。 自作問題を考えて、自分で解法をまとめる作業楽しいんだけど放出のタイミングがわからない。

色々やっている内に夕食の時間になり食べた。サッサと食べてしまい SRM に備えていた。 が、しかし自分は大事なことを見落としていた。SRM 807 はどうやら Only rated for Div. 2 らしかった。 昨日の日記に黄色になりたいとか書いていたが理論上不可能なことだった。 直前にそのアナウンスに気づいたが、Combined とのことで多分難しい問題もあるだろうということで参加した。

A 問題。文字列 $ S $ が与えられて、文字列当てゲームみたいなことをする。 文字列を推測する側のプレイヤーが文字を指定すると、その文字が書かれた index が全て明かされる。 推測する側のプレイヤーが指定した文字のリストが与えられるので、現在推測される文字列を不明な位置を '_' として返せ、と言う問題。 無難に $ 26|S| $ 回ループして処理した。

B 問題。長さ $ N $ の整数列 $ A $ を考える。このうち $ 1 $ つの値がわからなくなっている。 この数列は、すべての要素の平均の値が数列中に現れるという性質を持つ必要がある。 $ N - 1 $ 個の要素が与えられるので残り一個の整数の候補のリストを返せ、という問題。 数式を書けばよくて、$ \frac{ \sum _ {i=1} ^ {N - 1} A_i + X}{N} = A_k \quad (1 \leq k \leq N - 1) $ の $ X $ を求めれば良くて簡単な一次方程式。 と思いきや、$ \frac{ \sum _ {i=1} ^ {N - 1} A_i + X}{N} = X $ も考える必要がある。Hack のためにこれが要るケースを作っておいた。 最後に重複を除けば OK。

C 問題。長さ $ N $ の整数列 $ A $ が与えられる。 十進数で考えたときに $ 2 $ 整数の「違い」を「足りない桁は $ 0 $ 埋めして違っている桁の数字の数」と定義したときの全てのペアに対する「違い」の和を求めよ、という問題。 こういうのは桁ごとに見る。以上。

D 問題。長さ $ N $ の数列 $ A $ と $ LO,HI $ という整数が与えられる。 $ LO $ より大きく、$ HI $ 以下の部分和の個数を数えよ(和が同じでも index の set が異なれば異なる)、と言う問題。 制約を見ると $ LO,HI $ が大きく、 $ N \leq 40 $ 。こんなのは半分全列挙する。以上。 upper_bound と lower_bound を取り違えていて頭を悩ませていたのは内緒。

そんなこんなで結局難易度も Div.2 レベルだった。Combined とは一体…!? Hack Phase に入ったので B 問題の Hack を試みるも、意外とみんな $ X $ そのものが平均になるケースを見落としていなかった。 偉いなみんな。一人見落としを発見したため Hack した。気が付くと、unrated の人たちが rated の人の提出を撃墜しまくっていてワロタ。

ビックリするほど得るものがないセットだったのだが、問題の質自体は悪くないと思った。

SRM が早い時間だったため、作業をしたりしていた。

余談だが、世の中に Online Judge が多く存在している。これを作ってみるのもまた面白いとは思うのだが、初期制作の時間コストはもちろん、維持コストがかかるし実際に人が使うとなるとどのぐらいアクセスされるとか色々な事を考える必要があって面倒な気がする。 そこでクソみたいな Offline の Judge が一つぐらいあってもいいんじゃないかと思って作ろうと時々考えていて設計について調べものをしている。 時間ができたタイミングで一旦形にしたい。 名前はそうだな Arien Offline Judge で AOJ とかどうかな?怒られそう。

06/10 (THU)

6:50 起床。木曜は早起きすることにしているのだが、他の人のバランスが悪くて体調悪化に貢献している気がしてならない。 依然として典型90 を処理していないため朝の Twitter 確認ができない…

いつもこの時間に起きて支度をして朝食を食べて大学に向かうと時間はちょうどいいのだが、満員電車で気分最悪になる。 一限はオンラインで録画が存在しているため、今日は一回時間をズラして登校することに決めた。

結論から言うとズラして登校はかなり快適だった。問題点としては講義を録画で受けることになるため真剣みが半減する。 まあもともと院に入って超真剣に聞く講義などあまりないので気にならないかもしれない。

もう一つ今日試したことがある。行きにゲームセンターに行くことである。 今まで大学の帰りにゲームセンターに行っていたのだが、帰りはシンプルに疲れていて下手くそだったりするし、 なにより夕方以降は人が多くて待ちが多く発生するというのがストレスフルだ。 行きにゲーセンに行けばこの問題が解決しそうと思って試した。 真昼間から初手ゲームセンターに行くという行為自体に若干の抵抗感があることを除けばよかった。 というか学部生の時は昼に授業が入っていなければ普通にみんなでゲーセンに向かった気がするし、どうでもいいな。

f:id:spider_0859:20210612010013j:plain:w300
INSECTICIDE [HVN] PUC うまい

元気なこともあって、普通に成果が出る。気分よく大学に向かうことに成功。 しかし、肝心の研究の作業自体は難航しているんだよね(かなり困っています)。

~大学で時間を過ごす~

帰宅。行きにゲーセンに行くというのは、帰りが遅くなることを防ぐという効果も望めそうなので今後も導入していこうかな。 いつも木曜日に食べているタンドリーチキン丼の画像を一回も週記に上げてないことに気づいたので、来週はアップしようと思う。

夕食を食べて、胃を休ませながら CLIST を開く。今日は Div.3 であることを思い出す。 時間が来た。相当に眠いが諦めて(?)出場する。

A 問題。$ N $ 個の石が与えられてそれぞれの力が $ A_i $ で与えられる。力は distinct である。一回の操作で左右端のどちらかから石を取り出すことができる。力が最大と最小の石を両方取るには最小で何回の操作が必要か、という問題。 distinct なので最大最小の石の index を事前にもっておいて、それぞれの石について左右のどちらから取るかを全探索することで最小回数が分かる。

B 問題。$ N $ 人の子供がいて $ i $ 番目の子供は $ A_i $ 個のキャンディを持っている。子供を何人か選んでキャンディを全て預かり、それらのキャンディを自由に再分配することができる。最終的にすべての子供が持っているキャンディの数を同じにしたい。この時最小の選ぶ子供の人数を答えよ、という問題。まずキャンディの数の平均が整数になっている必要がある。あとは平均より多くの数のキャンディを持っている子供を選択すれば十分。

C 問題。長さ $ N $ の整数列 $ A $ が与えられて、$ L \leq A_i + A_j \leq R $ となるような $ i,j (i<j) $ の組を数え上げろ、という問題。 昨日の SRM の D の半分全列挙マージパートと同じ。

D 問題。$ A $ と $ B $ の $ 2 $ つの整数が与えられる。 $ 1 $ 回の操作では、それぞれの数をその正の約数で割る。 ちょうど $ K $ 回の操作で、$ A=B $ にすることはできるかどうか判定しろ、という問題。 $ A,B $ の一方がもう一方の約数になっている場合回数の下限は $ 1 $ 回。しかし $ A=B $ の場合のみ $ 2 $ 回になる。そのほかの場合も $ 2 $ 回。次に上限を考えると、$ A,B $ の素因数の数の和が操作回数上限である。よってこれに合うようにする。 素因数の数を求めるパートが一番つらいが、これは $ \sqrt{10^{9}} $ までの素因数を事前に列挙しておくのが良いらしい。 本番中は焦って高速素因数分解を yosupo judge からパクってきたが、なんか System Test で落ちていた(涙…)。

E 問題。嫌がらせ問題なので本番中は一回飛ばした。文字列を変数に代入する文と、 $ 2 $ つの変数を結合してできた文字列を変数に代入する文からなるプログラムがあって、最後の分で代入された文字列の中に "haha" という文字列がいくつ存在するか答えよという問題。変数名や単一の文字列は $ 5 $ 文字以内。 アイディア自体は簡単で、連想配列とかに変数の中身を持っていれば処理できるが $ N \leq 50 $ ぐらいあり、愚直は通らない。 よって、変数の内容の prefix, suffix を $ 3 $ 文字まで持つことにする。また文字列中に存在する "haha" の数も持っておく。こうすることで、後は丁寧に初期化や結合を掛ければ解けた。 結合部分の文字列に "haha" が $ 2 $ つ含まれる場合を忘れていてコンテスト中に合わせることはできなかった。

F 問題。初期値 $ L $ として $ 1 $ ずつ足していって $ R $ にすることを考える。$ R - L $ 回のの演算で変化した桁の数の合計を答えよ、という問題。$ 10^{x} $ の倍数になるときに $ x+1 $ 桁だけ変化していることに気づくので、$ 10^{k} \quad (0 \leq k \leq 9) $ の倍数の数を足し上げれば解ける。面倒なので $ L=0 $ の問題を解けば引き算で良い。

G 問題。$ X $ 個の赤いボールと $ Y $ 個の青いボールがあって、これらを使って $ A $ 個の赤いボールと $ B $ 個の青いボールのセット、もしくは $ B $ 個の赤いボールと $ A $ 個の青いボールのセットを作りたい。作れる最大のセットの数を求めよ、という問題。 こういうのはとりあえず数式を立てると良さそう。

$$ \left \{ \begin{array}{l} Ax+By \leq X \\ Bx+Ay \leq Y \end{array} \right . $$

上の式で $ x+y $ を最大化したい。$ x $ を固定すると、$ y $ の最大値は $ \min( \lfloor \frac{X - Ax}{B} \rfloor, \lfloor \frac{Y - Bx}{A} \rfloor) $ と決まることに気づく。$ f(x) = x+y = x + \min( \lfloor \frac{X - Ax}{B} \rfloor, \lfloor \frac{Y - Bx}{A} \rfloor) $ と置けて、これは上に凸である(コンテスト本番は直感的に感じた)。真面目に言うと、$ f_1(x) = x $ は自明に凸関数で、$ f_2(x) = \min( \lfloor \frac{X - Ax}{B} \rfloor, \lfloor \frac{Y - Bx}{A} \rfloor) $ は凸関数と凸関数の $ \min $ なので凸関数。凸関数の和は凸関数なので $ f(x) $ は凸関数。 よってあとは三分探索をした。床関数を抜いて、実数で比較は行った(でないと壊れそうだったため)。

後で editorial を見たら、$ n $ セット作ることが可能かどうかを判定して二分探索する方針を取っていて、式を変形することで $ 4 $ つの条件を満たしているかどうかで良いという解き方をしていた。賢い。

06/11 (FRI)

11:00 ぐらい起床。最悪。例によって典型を処理していないため(以下略)

朝食にワッフルを食べる。研究作業をしていき、昼の時間になって昼食を食べる。 こいついつも飯を食っているな。

14:30 ぐらいからはマジで最近だれも質問に来ない TA をやる。この時間も作業自体はしている。 16:30 からはゼミがある。そういえば来週のゼミのスライドまだ一ミリも作っていない。 今回は余裕を持って完成させたいが…

18:30 になってゼミも MTG も全てが終了する。研究はなかなか面倒ごとが起きていて困るがまあこんなもんだろうという感じで金曜をおしまいにした。

明日の ARC の配点が来ていた。400 500 600 700 800 1200 らしい。 maroon さん単独W回だし、敗北する臭いがかなり強い。 特に最近難しい問題に全然ちゃんと取り組んでいないため、やばい。

夕食をたべる。 土曜日にここを書いているのだが、夕食を食べた後何をしていたのか全然思い出せない。 とりあえず寝る前に sak さんが Twitter でスペースを開いていたためお邪魔をしたことだけ覚えている。

びっくりするぐらい本日の内容が薄い。 日記にできないことが多い日はこうなりがちなのかな…

06/12 (SAT)

12:00 起床。土曜を無駄にする天才になっている。かなりウケる。いや全然ウケない。

朝飯は諦めて、昼飯はマックを食す。UberEats。 僕マックを食べる時ダブルチーズバーゲーだけでは物足りなくて、チーズバーガーを足すとかいう珍プレイをしているんですが、 皆さん足りないときどうしているんだろう…?気になります。 というかまた気づいちゃったんだけど、マックですらチーズと牛のコンビに洗脳されているな、自分。 これからプロチー牛野郎として生きていこうかな。

最近もこうの動画をあまり確認していなかったため、確認する。 やっぱりもこうは頭がおかしい。妙にスマートな量産型 YouTuber なんかより頭のおかしいもこうの方がずっと面白いと思うんだけどあまり共感が得られない。 あとなんか、もこうが世にも奇妙な物語に出るらしい。草。見ようかな。

友人と通話の予定があったのでちょっと話した。研究室以外の人と話す機会を大切にしていきたいなと思った。

今日が ARC であることを思い出し危機感を覚える。 競技プログラミング開始! というわけで競技プログラミングをしていた。新たに難しい問題を解くとかはしなかった。

夕食後、ARC 開始。

Tokio Marine & Nichido Fire Insurance Programming Contest 2021(AtCoder Regular Contest 122) - AtCoder

A 問題。 長さ $ N $ 非負整数列 $ A $ が与えられる。各項の間に +- を入れる。その時、連続して - が存在しないような書き入れ方を良い式と呼ぶ。 良い式の値の和を $ \bmod 10^{9} + 7$ で求めよ、という問題。 難しい。 $ i $ 番目までの隙間を見て、- が $ j $ 個連続している場合の数は DP で求められる。 $ j \leq 1 $ のため $ O(N) $ で求められる。この DP table を利用しながら $ i $ 番目までの隙間を見て - が $ j $ 個連続している場合の数を DP で求めた。AC。 かなり混乱した。

B 問題。$ N $ 個のシナリオが与えられる。$ i $ 番目のシナリオでは $ A_i $ 円を失ってしまう。それぞれのシナリオは等確率で起こる。 $ x $ 円 (任意の値) 払って保険に入ることによって、$ A_i $ 円を失った時に $ \min(A_i, 2x) $ 円補填してもらえる。 最終的に失うお金の期待値の最小値を求めよ。 明らかに $ 2x $ が $ A_i $ 以上かどうかで性質が変わる。$ A $ をソートして累積和を事前計算することで、 $ x = \frac{A_i}{2} $ の場合を全て試すのを高速にできる。AC。

C 問題。むずすぎ。本番は落とした。フィボナッチっぽいことに気づいていたのに、考察を続ける堪え性がなかった。 任意の整数は、隣接しないフィボナッチ数の和で表現できるため、計算するとちょうど $ 130 $ ぐらいで目標を達成できる。 明らかに 3,4 を繰り返さないと間に合わない大きさの数字だったので、早く気づくべきだった。

D 問題。本番わかったのだが、落とした(???)。$ 2N $ の非負整数が与えられて、$ 2 $ 人が交互に数字を取ってきてその xor が黒板に書かれて、最後に黒板に書かれた最大値がスコアになる。 先行の人は最大化したいし、後攻の人は最小化したい。 xor の最大値を考えるので、整数列中で一番高い位置の pop している bit に着目するのが良いだろう。 着目すると、この bit が pop している整数が偶数個なら、ミラーリング戦略を取ることでスコアでその bit が立つことを防げて最適。 奇数個なら、スコアで必ずその bit が立ってしまう。故に、後攻はなるべくそれより下位の bit で小さくしたい。 着目している bit が立っている整数集合とそうでない集合間の要素同士の xor でもっと小さいものが答えになる。これは Binary Trie で効率よくわかる

偶数の場合に立ち戻る。偶数の場合はミラーリング戦略で良いが、どれとどれを組ませるかは後攻が決めることができるので再帰してその右側の bit で同じ問題を解く。 桁数が $ 30 $ 程度なので再帰しても十分間に合う。また着目した bit が pop していない整数の集合に対しても問題を解いて、結果をマージする。 これで解けたはずだったが、chmin のところが chmax になっていて落とした・・・無念・・・

E 問題。本番は読んだだけだった。冷静になると、比較的にわかりやすい貪欲で解けることに気づいた。 ただ ad-hoc 要素が強いな。本番この問題に突撃するのは勇気が要りそうだ。 この問題と D は記事にしようかな。

普通に青落ちしてしまった。まあ、気長に競プロやっていこう・・・。D 落としてなかったら落ちてないし、まあ実力は黄色ってことで・・・。

06/13 (SUN)

11:00 起床。ワッフルを朝食に食べる。

さらっと昨日の ARC のコンテスト復習まで含めて昨日の日記に書いてしまったが、ARC の復習をしていた。 E 問題が貪欲なのに驚いた。ARC E はまあまあな頻度で気づき枠が出るなぁと思いを馳せていた。

昼飯を食べてしばらくはゆっくりしていたが、普通に明日のゼミのスライドを一ミリも作っていないことを思い出す。 読んだ論文の中から発表する論文を決めて、読み直す。

読み終わる。 スライドを作っている。B4 にもわかるようなスライドにしようとした結果、辛い思いをしている。 そして多分これは B4 がわかるかどうか怪しい気がする。あまりにも救いのない作業に涙が出てくる。

間に夕食を食う。 ABC があるので何もしていないけど出てみる。まあ黄色 perf は出るやろ・・・。

AtCoder Beginner Contest 205 - AtCoder

A 問題。A で実数問題でた。珍しい。

B 問題。与えられる配列 $ A $ が $ {1,2,...,N} $ の並び替えか確かめる問題。ソートする。

C 問題。$ A^{C} $ と $ B^{C} $ の大小を比較する問題。負数があってめんどくさい。実数入力がない分だけましだけど辛かった。

D 問題。配列 $ A $ と $ Q $ 個のクエリが与えられる。 各クエリは、$ K $ が与えられるので、$ A $ に含まれない正整数で $ K $ 番目のものを答えよという問題。 ソートしてそこまでに幾つ正整数があるかをメモして二分探索した。混乱した。

E 問題。左上が斜めに切り取られた経路数問題に落ちることはわりとすぐ気づいた。$ O(N^{2}) $ しか思いつかない。 というかこれを書いている今も実は解けていない。HELP! ここで精神崩壊してしまった。

F 問題。グリッドが与えられる。$ N $ 個の部分矩形が与えられるので含まれるマスにコマを置ける。 同じ行や列にコマを $ 2 $ つ以上コマを置くことができない時、最大幾つコマを置けるか?という問題。 こんな問題 DP とか貪欲で解けるわけがない。最大流だなと思った。 しかし深刻なことに「同じマスに $ 2 $ つ以上置けない」に誤読していて間に合う気がしなかった。 コンテスト終了 $ 2 $ 分前に気づいた。書きなおしたが間に合わない。助けてくれ!!!!!!!!!!!!

結果はさらにレートを削ることになった。 それはそうと E が解けないのはダメらしい。そこは素直に反省します。

スライドの手直しに戻る。 今週末はこの作業中に日が明けた。カラスがバカうるさい。奴ら深夜に鳴くのマジで何?

今週は競プロがあまりできなかったので、来週は競プロを中心に生活を回したいと思ったりした。 それでは。

週記(2021/05/31-2021/06/6)

05/31 (MON)

9:15 起床。まあまあ睡眠の質は良かった。 なんかAtCoder黄色になった夢をみた。いや、来週どうせなれるから夢に見る必要がないと思うのだが(フラグ)。

大学に向かいつつ、今日の典型を確認する。

https://atcoder.jp/contests/typical90/tasks/typical90_bb

問題概要。$ N $ 人の研究者がいる。$ M $ 個の共著論文がある。$ i $ 番目の共著論文には、$ K_i $ 人が携わっていてそれぞれの人の番号が与えられる。 研究者 $ 1 $ から共著したグループ内の移動を $ +1 $ としてそれぞれの研究者について、何回の移動で到達できるかを求めよ。研究者から $ 1 $ から到達不可能ならそれを報告せよ。

見た目どう見ても BFS である。そのままナイーブにグラフを作成するとグラフのサイズが $ O(N^{2}) $ になる。 陽にグラフを構成しなければ、グループごとに訪問フラグを持ってやって BFS をそのまま実行することができる気がする。

ただ、典型ではこういうある集合内で縦横無尽に辺を貼る問題の辺の数を減らすテクニックがある。 グループの代表のノードを作ってやる。そうすることによって代表のノードに移動する際に $ +1 $ のコストを払って、 逆に代表のノードから各要素のノードに移動にはノーコストで移動できるとすることで辺の数を減らして等価な計算ができる。 こうすると、01DFS になるが、$ 0.5 $ ずつコストを分割すれば BFS をそのまま使うことができそうだ。

代表のノードを考えると、二部グラフのように考えることができる場合も多く一考の余地あるテクニックな気がする。

大学に着く。作業をし始めるも、今日は溜めに溜めた TA の採点作業をしなければならない。 教授からも、はやく採点しろやというメールが来てしまう。本当に申し訳なさしかない。 そんなこんなでこの日は採点をメインにやっていた。Javaオブジェクト指向言語を入門するみたいな講義内容のため、難しくはない。 学部生の解答が zip で与えられるため、このダウンロードがボトルネックになってしまう。 なぜなら、ここは手動でやる必要があるからだ。正しくは、認証を真面目にやれば自動化できるのだろうが流石に労力に自動化のメリットが見合っていなさすぎる。 採点をマッハで終わらすために、実は事前に zip を指定の名前のフォルダに unzip して中の java ファイルを全て javac かけて score.txt と言うファイルを作成した上で、vimjava ファイルと score.txt を開く、というスクリプトを作っておき、また採点で見るべき箇所もチェック済みであった。

というわけで、採点に励んでいた。というか家に採点用に整備した PC を忘れてきたので早めに帰宅して採点をしていた。 よって、競技プログラミングもやっていないし、買ったジャンプも放置していた。

先週の週記の最後で述べたコドフォのコンテストへの煽り気味お気持ち表明が -7 になっていた。まあ煽ったのだからそうなるだろうという気持ちになりつつ、ちょっと下の Red Coder の煽りコメントがそこそこ Upvote されていて、ratism を感じるなどしていた。

まあなぜわざわざお気持ち表明したかというと、自分は次の日の朝を犠牲にしてまで深夜コンテストに出て writer の定義を信じたのに裏切られて不快感を得たのに、writer が不快感を得ないのは不公平だと思って不快感を与えようと思ったとかいう小学生的で幼稚な理由である(もちろんちょっとは unrated にも期待していた)。 ちょっと申し訳ないことをしたかなとも思ったけど、writer は全く悪いと思っていなくて「たくさんの tester が見ても nested list の定義には何の疑問もなかったぜ」みたいな居直りをしていたので、やっぱ不快感を与えて正解だと思いなおした。フレーバー要素に定義の本質を置いていいんだったらもういっそ形式的な定義は一切書かないでコンテスト開いてくれよ、きっと称賛されるよ。 またイライラしてきてしまったので今日でこのことを考えるのはもうやめるぜ。

そんなことで特にブログにかけるような活動をせずに一日を終えた。

06/01 (TUE)

6 月になった。11:30 起床。遅すぎる。朝食を食べながら、今日の典型を確認する。

https://atcoder.jp/contests/typical90/tasks/typical90_bc

$ N $ 個の整数が与えられる。このうち $ 5 $ 個を選んで積を取ったときに、$ P $ で割った余りが $ Q $ になるような選び方は何通りあるかを求めよ、と言う問題。

DP をすると、状態が多いな~とか一瞬思ったがそもそも $ N \leq 100 $ なので $ \binom{100}{5} = 75,287,520 $ なので全探索が可能である。まあ★2 だしな。

そうこうしているうちに昼飯の時間になる。 とはいえ、今日は家に人が全然いないため、残り物を食すという感じだ。

昼から後は、基本的に作業をしていたり、ピアノを弾いていたりした。 実家ぐらしだと、逆に一人の時間がかなり貴重だったりする。 貴重な時間はあっと言う間に去り、夕食の時間になる。

驚くべきことに全然競技プログラミングもやってないし、ジャンプも読んでいない。 仕方ないので、今練習している曲の適当な人の演奏の YouTube のリンクでも貼っておくか。

www.youtube.com

改めて上から見せられると、右手のカバー範囲がところどころぶっ壊れてないか? 音楽ゲームでこんな譜面を収録したらきっと怒られるに違いない。

夕食は外出して、サイゼリヤに行った。ラストオーダーの 10 分前らしい。駆け込みでごめんさない。 マルゲリータピザ、ペペロンチーノ、ポテト、イタリアンプリンという自分の中の鉄板メニューを頼んだ。 個人的にサイゼリヤのイタリアンプリンクッソ美味いと思うんだけど、あまり共感が得られない。

帰り際にゲーセンに少し寄ることになったが、ボルテのメンテがカスすぎて一気に萎えてすぐに帰宅。 帰宅して、今日の典型を通すことにした。

全探索ができると既に述べたが、多分典型の想定では DFS を使って全探索をするのではないかと疑っている。 なぜなら、わざわざ $ 5 $ というループをネストさせるにはデカい数字を選んだということは「$ n $ 重ループは DFS」みたいな典型を言いたいんではないかと考えた。というわけでいつも通り DFS で全探索を書いた。AC。1 sec ぐらいかかっている。 マクロを使えば $ 5 $ 重ループわけないと思ったため書きなおして、最適化を #pragma で指定したら 659ms になった。

昨日の典型もまだ書いていないので通す。 辺の本数を少なくして BFS や 01BFS をする解法は実装がいつも通りで楽。 それぞれの研究者が関わっている共著リストと、それぞれの共著に含まれる研究者リストをそれぞれ持っておくことによってグラフを陽に持たずにそのまま BFS をすることもできるぜ!と思うけど、コンテスト中はこの解法を採用することはなさそう。

E - White Pawn の実装方針がかなり悪かったので再考する。

コンテスト中は、$ Y $ 方向に圧縮(必要な区間のみを vector に載せる)した上で in-place DP をやって通した。しかしこれではあまりにも事前処理とか offset とか面倒臭すぎて時間がかかりすぎる。なんとかならないか。よくよく考えると $ Y $ 方向に実際に圧縮する必要はないんじゃないかと思った。黒のポーンの隣接する $ Y $ 座標に既に到達可能かどうかが判別できればいいので、std::set を使えば煩わしい処理から解放されそうだ。大分楽になった気がする。明示的な圧縮は往々にしてクソめんどくさいため、std::setstd::map でしなくてよくなりそうなら、しない方がよさそうだな…

F - Weed を解けたと言いながら通してなかったので心配になりやることにした。 勘違いが解けたところから書く。勘違いがとけると、青木君が残す部分は全然区間になっていないことがわかる。 特に強い制約のない歯抜けの選択最適化なので貪欲は厳しいなと思い DP に思いを馳せる。 高橋君の操作は残った集合の最大値の半分を超える要素を削除するため、大きさでソートをしておく。 最初は $ dp[i][j] \cdots $ 昇順 $ i $ 番目の数字まで見て、$ j $ 個の数字を青木君が削除したときの高橋君の操作回数、という DP を考える。ある数字を青木君が削除するかどうかで遷移をしていくのだが、削除しない場合その数字を $ X $ として $ 2X $ 未満の数字までは削除しないようにするのが明らかに最適。これらを削除しなくても高橋君の操作回数は減らないし青木君の操作回数は減らせるためである。 しかし、このアルゴリズムでは明らかに $ O(N^{2}) $ かかってしまっている。よく考えると $ X $ 以上 $ 2X $ 未満を残すと高橋君の操作回数が $ 1 $ 増えるので、高橋君の操作回数は最大でも $ O(\log{A _ {max}}) $ である。よって DP の値と $ j $ を入れ替えることで $ O(N \log{A _ {max}}) $ になり、解けた。AC。

DP table の値と状態の一要素を入れ替えて状態数を落とすのはナップザック問題の変種にもあったなあと思ったりした。勘違いしなければ、なんてことはない問題だったので割と反省している…

眠いので今日はこのへんで寝る。

06/02 (WED)

10:50 起床。目覚ましをかけ忘れた。 朝食のカステラをほおばりながら、今日の典型を確認する。

https://atcoder.jp/contests/typical90/tasks/typical90_bd

問題概要。$ N $ 日間福袋が販売されている。$ i $ 日目の福袋は $ A_i $ 円のものと $ B_i $ 円のものの二種類ある。各日付についてどちらかを買わなければならない。この時 $ N $ 日間で購入した福袋の合計額が $ S $ 円になるような買い方が存在する場合は買い方を、存在しない場合は Impossible と出力せよ。

$ S \leq 10^{5} $ で $ N \leq 100 $ を確認して $ O(NS) $ のナップザック DP をすれば良いことが明らか。復元もいつも通りやる。現代人、ナップザックは全員履修しているため実際にこれが ABC-E で出題されたらかなり簡単な部類だと思う。

今日はピアノなので手ならしも兼ねて練習をする。幸いにも家に一人である。 しかし今日は暑い。ピアノを照らすライトは白熱灯なのでもう気が狂うほど暑いんじゃ。

昼飯はマックに食べに行った。チーズキチガイなのでダブルチーズバーガーのセット(ポテト L)と、シャカシャカチキン(チェダーチーズ)を購入した。モバイルオーダーをつかったためスマホ以外手ぶらで食べに行けるのが嬉しい。あと、単純に早めに注文すれば待ち時間が存在しなくなるのもモバイルオーダーは優れていると思う。心なしか並んでいる人より優越感に浸れる(?)。

f:id:spider_0859:20210602164517j:plain:w300
チーズキチガイのためのマック

マックから帰ってきてピアノを続行。そしてピアノ教室に足を運び、あまりの下手くそさに沈没して帰ってくる。

この時点で典型のジャッジが追加されているので書く。 今まで DP の復元は全て、prev という配列を用意して手前の状態を保存しておくという手段を脳死で取っていた。 もちろんパターン化と言う意味ではこれが一番いいのかもしれないが、遷移の種類を考えた上で良い情報の持ち方を選ぶのも大切に最近思えてきた。 今回の場合、$ A $ と $ B $ でどっちを選んで遷移してきたかを配列に保存しておいた。結果から逆算して選択を求めるのはしばしば面倒なので、このように選択したものを保存しておけるのであればそうすると復元が楽かもしれない。選択から元の状態を計算するのか、元の状態から選択を計算するのかどっちが楽かという問題な気がしてきた。AC。

今日 TCO Round2B があったような気がしたので Arena を開くと will start in 2 hours 41 minutes. って書いてあってクソ焦る。 完全に夜中だと思い込んでいた。

ウォーミングアップを兼ねて、令和の ABC を $ 2 $ 個程復習した。

TCO Round2B が始まる。

Easy: 前回の TCO Round2A の Easy は 5000 文字を超える凄絶な問題文だったが今回は逆にめちゃくちゃ短くてびっくりした。 桁を見た時に交互に偶奇が配置されているような数字を昇順に並べた数列の $ K $ 番目の数字を答えよ、という問題。 こういう問題は $ n $ 桁の場合の数や、左から決めた時の場合の数が高速にわかる場合は貪欲でできることが知られる。偶奇が交互に来るので一番大きな桁が一旦決まってしまえば、そこからは $ 1 $ 桁につき $ 5 $ 通りずつ存在する。桁数を決めた後、左から決めていく。$ 1 $ 桁目は 1-indexed で $ 2 $ 桁目以降は 奇数/偶数の index であることに注意。実装が下手すぎて参っていた。実装でワタつくぐらいなら桁 DP の二分探索でも良かったな。

Med: ロボットが $ N $ 台あって,$ 1 \leq M < 10^{6} $ の番号づけされたタスクが与えられる。同じ番号のタスクが割り当てられているロボットが $ K $ 連続で存在する箇所がどこかであるようにするために、いくつかのロボットを事前に除去する。最低幾つのロボットを除去すれば良いか、という問題。最初は見た目から全探索ベースで DP を考えた。naive にやると爆発。高速化を考えると、同じ番号のタスクが割り当てられている中で $ K - 1 $ 個先のロボットを前計算しておけば高速な DP ができるなと思った。しかし冷静にほぼ前計算で答えが出るので全てのタスクについて答えを求めて min をとる。

Hard: 分数の分母が与えられ、分子分母に共通する桁を順次消していくという操作を繰り返して最初と同じ値になるような分数を発見して分子を答えよ、という問題。まず分子になる数字は分母の約数しかない(約分できないといけない)。制約が $ D < 10^{7} $ なので約数の個数は $ 500 $ にも満たない。元の分母 $ D $ 分子 $ N $ がわかっているので、分母のうちどれを残すかを bit 全探索する。その後分子についてもどれを残すか bit 探索して削除した数字の分布が同じで分数の値が元と同じなら答えとなる。分母と同じ数だけ桁を削除するので定数倍改善が可能。高速化をしなくてもかなり厳し目に評価して $ 448 \times 2^{14} \times 7 = 51,380,224 $ なので耐えてる気がするが、定数倍改善をすれば $ 2 $ 倍以上早くなるはずなので心の余裕が生まれそう。実装が間に合わず落とした。けど人類が落としまくっていたので耐え。

レーティングが 1499 になった。草。TopCoder 適当すぎて黄色にすらなれてないの悲しいので次回なろうね。

06/03(THU)

8:30 起床。スマホを充電器につないで寝なかったためアラームが鳴らず寝坊。仕方がないので今週は家から一限を受けることにした。 とりあえず今日の典型を確認する。★6 だ。

https://atcoder.jp/contests/typical90/tasks/typical90_be

問題概要。$ M $ 枚のパネルがあって、最初は全て裏面を向いている。$ N $ 個のスイッチがあり、それぞれを押すことによっては対応するパネルの集合をひっくり返すことができる。 パネルの状態が一つ与えられるので、スイッチはそれぞれ高々 $ 1 $ 回推すことができる時そのパネル状態を作るようなボタンの押し方は何通りあるか。$ \bmod 998244353 $ で答えよ。

一目見て簡単ではないし、自分が苦手そうな雰囲気を感じたので一旦忘れることにした。 というか 9:00 から講義なので、普通に見た瞬間わからなかったら考える時間なかった。

というわけで講義を受ける。ふむふむ。講義内容に関しては触れることがないぜ。 言えることがあるとすれば、Microsoft Azure をオモチャとして使う課題がある。 大学 1, 2 年ならこの程度の事で喜んじゃうだろうが、もうだいぶ大学に慣れてしまって別にと言う感じになっている。 いや、修士 1 年だしはしゃいだ方がいいかもしれない。

講義が終わると作業をする。今週は結構作業をしている気がする。 というのも一番気が狂いそうだったパートはなんか解決したっぽくてやる気が出てきたというのがある。 今日の MTG では教授に「久々に〇〇くんが明るい声で安心した」と笑われた。草。 自分は外側から見ると相当分かり易い人間らしく、ちょっと恥ずかしい。 ともあれ、作業が楽しいフェーズに入っている気がする。この調子で話がまとまってくれると嬉しいな。 C++ のコードを C で書き直すとかいう拷問をやっていた時はどうなるかと思った。

しばらく元気に作業をしたり、やるべきことを処理したりしていた。 気が付いたら 18:00 を普通に回っていた気がする。かねこさんがボルテ配信をしているので覗くことにした。 上手すぎて作業をちまちまやりながら左側に配信を表示していた。この時間本当に作業が進んでいなかったりする。

去年一年間リモートのマシンに接続するとき毎回パスワードを手入力していたんだけど、このままでは後輩に ssh key を生成して鍵で認証するようにしよう!と言えないので仕方なく公開鍵をマシンにぶち込んだ。 目先のことしか考えられないゴミ野郎なのでわかっていてもこういう設定を後回しにするんだけど、やめた方がいいな。

そんなこんなで夕食の時間になる。美味しい。オムライスを作ってもらえた。オムライスってなんであんなに美味しいの?

食後は Twitter 閲覧、YouTube 閲覧に力を入れていた。この時間が多分一日の中で一番生産性がない。 適当に閲覧している自分でも結構な時間を使ってしまうので、好きな YouTuber や VTuber とか追っている人って相当時間使ってそうだしすげえなあと思ったりした。

気が付いたら 11:00 を過ぎていた。競技プログラミングをやっておこうということになる。 A - AtCoder Jumper を開く。セグ木みたいな形を考える。ウンウンうなっても全然条件を満たせないことに気づく。解けない。完全に参った。青 diff に対して解説を見るのも悔しいので見ないで放置を決める。

そういえば、放置と言えば今日の典型を考えていなかったのでやるか。線形代数みたいだな。 01 ベクトルが $ N $ 本あって、その span みたいなことに思いを馳せる。とりあえず、$ N $ 本の張る span 内に目的の 01 ベクトルがなければ答えは自明に $ 0 $ だと思う。いや span って言っていいのか?xor 結合で張られる空間を何と呼べばいいんだ代数学など何もわからないのでこのまま線形代数と同じように考えて進める。一次独立なベクトルが張る span に目的のベクトルが含まれる時、構成は明らかに一意(線形独立性から一次結合が一意なのはすぐわかる)。$ N $ 本中で、一次独立なベクトルの最大本数を $ L $ 本として、この $ L $ 本が張る span は全体の span と当然同じ。$ N - L $ 本のベクトルはこの span 内にあり、$ 2^{N - L} $ 通りの一次結合も当然すべて span 内にある。よってそれぞれに対して一意な構成が存在する。したがって答えは不可能なら $ 0 $ 、可能なら $ 2^{N - L} $ となる。

実装は一次独立なベクトル集合を管理するんだけど、制約が微妙に大きくてベクトルを整数で表現できなくて面倒くさい。 普通に掃き出しをすることを考えると $ O(NM^{2}) $ かかる。まあ、間に合うやろ。AC。33ms。最適化されてないかこれってぐらい速い。

64 ビット整数を $ 5 $ つつなげていつもの高速かつ簡素な xor 掃き出しをやってみる。

有り体に言うとこれをして楽をしたい。

TODO ←こう書きつつ結局今週書かなかったな。来週チョロ書きします。

06/04 (FRI)

9:00 起床。眠い。ダラダラしながら、昨日大学に行かなかったので今日は行くことにした。

行きの電車の中で今日の典型を確認する。★4 か。

問題概要。$ 5 $ 桁の数を表示できる電卓があり、ボタンを押すと表示されている数字を $ X $ として桁和を $ Y $ とすると、$ X+Y $ を $ 10^{5} $ で割った余りの数に変化する。 最初に表示されている数字が与えられるので、ボタンを $ K $ 回押した後の数字を求めよ。

一番最初、朝と言うこともあり繰り上がりがあるから行列階乗は難しいな〜とかほざいていた。 冷静になると、functional graph で頂点数も $ 10^{5} $ なのでいつものサイクルゲーをやるかダブリングをやるかである。 サイクルゲーでやると実装は面倒だが、$ \log $ がつかないぐらいかな。

完全に余談だがこの手のダブリングをする時毎回適当に in-place にやろうとしてめんどくさくなってる。 更新待ち queue を持たないと完全に in-place にはできない。けどまあ queue を使って更新をするのまあまあ好きな実装。

大学について作業を開始するも、とんでもない失態を犯していたことに気が付く。 あまりにもとんでもない失態なのでとてもじゃないが書けない。複数人に迷惑をかけたので申し訳なかった…

金曜日は Java の講義の TA をしている。と言っても最近は全然質問が来なくて作業をしていることが多い。 Java の講義の前にもしかしたら典型のジャッジが来ているかも知れないと思い確認したら来ていたので投げる。AC。

TA 開始。今日は質問が来てビックリした。TA のあとはゼミがある。 失態を犯してしょんぼりしていたので、ゼミが終わったらおとなしく帰ることにした…つもりなのだが、楽しい気分になるためにゲーセンへ行く。

f:id:spider_0859:20210606172055j:plain:w300f:id:spider_0859:20210606172107j:plain:w300
割と全てうまかったが VVelcome!! [MXM] と Dyscontrolled Galaxy [MXM] 抜粋

翌日に久々に同期と一緒に音ゲーをすることになっていたので前日のウォーミングアップぐらいのつもりだったが、かなりうまかった。

そんなこんなで帰宅。音ゲーを毎日やらなくなってから音ゲーをすると疲れてしょうがない。 今日は Codeforces のコンテストがあったことを思い出す。家に帰って夕飯を食べてから体力回復のためにダラダラしていた。 開始直前は眠かったが、ガムを噛んで誤魔化した。

Dashboard - Educational Codeforces Round 110 (Rated for Div. 2) - Codeforces

A 問題。$ 4 $ 人でトーナメントをする。寂しいな。しかし一回戦で勝ち上がった $ 2 $ 人は $ 4 $ 人の中で強い方の半分でないと fair でない。トーナメントの組み合わせが与えられるため、fair かどうか判別せよ、という問題。意外と面倒臭い。勝ち上がった $ 2 $ 人と上から $ 2 $ 人をそれぞれ求めて一致するかチェックした。

B 問題。長さ $ N $ の数列 $ a $ が与えられる。$ \gcd({a_i, 2a_j}) > 0 \quad (i<j) $ のような組の数が最大になるように並び替えたときのその数を答えよ、という問題。$ a_i $ が偶数であれば $ j $ はなんでもよく、奇数同士偶数同士の組の数は順序に依存しないため偶数を左に持ってくれば OK。数え上げを丁寧にやらなくても $ O(N^{2}) $ が間に合うためこれで書いた。ちゃんと正当性を確認してから投げたので、早解き的には出遅れていた感はあるが個人的にはいい感じだった。

C 問題。$ 0 $ $ 1 $ ? からなる文字列が与えられる。? をうまく決めたときに $ 010101 \cdots $ か $ 101010 \cdots $ になるような文字列を beautiful と呼ぶ。beautiful な連続する部分文字列はいくつあるか、という問題。まず ? のみの文字列は beautiful だと思った。というか$ 1 $ つでも ? 以外の文字があれば上記のどっちのパターンを目標にするかが決まるな。 $ 1 $ が奇数 index にあるのと $ 0 $ が偶数 index にあるのは論理的な矛盾を起こさない。また index の偶奇を入れ替えた条件も矛盾がない。それ以外の共存パターンは不可能なのでこの条件を活かしつつ尺取りをすれば $ O(|S|) $ で解けそうだ。問題があって自分は尺取りがすごく苦手だ。案の定すごい時間をかけて通した。

D 問題。$ 2^{K} $ の人数が参加するトーナメントがある。$ 2^{K} - 1 $ 回の試合に関して、$ 0 $ $ 1 $ ? が与えられる。それぞれ、選手番号が小さい方が勝つ、大きい方が勝つ、どっちが勝つかわからない、という情報を与える。$ Q $ 個のクエリが与えられて、この情報が $ 1 $ つずつ変更される。それぞれの変更の後に優勝する可能性のある選手の数を答えよ、という問題。単純に考えると、トーナメントをシミュレーションしていけばいいが間に合わない。よく考えると、トーナメントは完全二分木の構造をしており、それぞれのノードがそこまで勝ち上がってくる可能性のある選手の数と考えると、一か所の情報が変わった時影響を受けるのはその祖先のノードだけである。よってクエリ毎に木の高さ程度しか計算量がかからず、全体 $ O(2^{K} \log K) $ で求まる。

E 問題。online を共用してくる問題だ。最初に木の root とそこにある金の量と単価が与えられる。クエリが $ 2 $ 種類 online で渡される。$ 1 $ つめのクエリでは指定したノードに子ノードをくっつける。金の量と単価も与えられる。$ 2 $ つめのクエリでは指定したノードから root へ移動していき指定された量の金を購入していく(足りない場合はできるだけ買う)。その過程で買った金の量とコストを出力する。ただし、子ノードの金の単価は親よりも高いという制約がある。

祖先ほどコストがかからないので、指定されたノードから root へのパスを考えたときに root から貪欲にとるのが最善なのはすぐわかる。しかし、愚直にこれをやると到底間に合わない。まだ金が残っている最も root に近い祖先を高速に見つける必要がある。offline ならニヤつきながら HLD で殴るのだが、多分 writer はそれをさせたくなかったのだろう…まあよく考えると木なので親は $ 1 $ つだしダブリングができる。というか忘れてたけど LCA ってこのダブリングでも求められたな。というわけでダブリングを書く。これで二分探索によって目的の祖先を見つけることが出来る。実装に手間取り時間がなかったので目標の金の量に達するまでこれを雑にループさせた。投げる。通った… 3000ms 弱あったと思う。

CDE の実装パートで時間を使っていたのがもったいなかったが、順位表を見る限り F は無理そうなので解くべき問題は全て通したと言える。めでたしめでたし。ただ E の TL だけがちょっと不安だ。

あとは D 問題は個人的に好きだったので Comment をした。前回意図的な negative な Comment をしたのでこれからは positive な Comment などもしていくぜ。就寝。

06/05 (SAT)

10:00 起床。今日は同期と遊びにいく予定だ。といっても秋葉原とかは混んでてまあいろんな意味でよくない(ゲームで待ちが発生して面白くないし、ご時世的にもね)ので、千葉の妙典とかいうところまで行った。初耳だった。まあ電車を調べると秋葉原と大差ない距離だったのでよかった。

ここで「イオン市川妙典店」とかいう文字列を見たので「てんてん」が含まれていて面白いなと思ってニヤニヤしながらツイートをしたら、「妙典」は「みょうでん」と読むらしく泣いてしまった。いや「でんてん」でも面白いかもしれない。

今日はマジで一日遊ぶつもりで実際そうした。昼から夜まで遊んだ。

f:id:spider_0859:20210606180538j:plain:w300
She Turns Me On 初見で PUC して 18 個。自分的にかなりうまい。

うまかったリザルトを一つだけ貼っておく。色々うまかった気がするが、あんまり写真を撮っていなかった。 久々に同期と一緒に音ゲーしたり飯を食ったりして楽しかった。少人数なら時々こうして会ってもよさそうだし今後もしていきたいな。 居た同期のうち半分がもう社会人になっているのですごい変な感じがした。

今日の典型問題に関しては、チラ見したがまともな解法が思いつかなかったため、日曜に回すことにした。

06/06 (SUN)

12:00 起床。最悪の目覚め。だがよく寝た。一回アラームを消したという記憶がある。

多分午前中は Twitter の TL には昨日の典型に関する情報が流れていると思い、見ないようにした。 朝食は諦めて昼食を食べた。

そういえば書き忘れていたが、昨日ゲーセンでカバンの中をガサゴソしているときに入っていた名札の安全ピンによって右手薬指を怪我した。綺麗な指し口だったのか、圧迫したらすぐに血も止まって特に痛くもなかった。 しかし今日は AtCoder の Rated で割と黄色になれるかどうかがかかっているのであまりパソコンに触らず安静にしていようと思った。 こういうとき、油断して普通に酷使するとまた血が噴き出すのである。

と言いながら、ずっとパソコンから離れていた。よくよく考えたら自分はあらゆる趣味、仕事、勉強・研究などを指を使って行っていることに気づく。マジでやることがなくなってしまい、漫画と YouTube でお茶を濁していた。

ところで最近、金色のガッシュの完全版を電子書籍として購入して読み始めた。金色のガッシュどこまで読んだのかもよく覚えていないし、一から読んでいくことにした。内容は面白いし、完全版は一冊のボリュームが大きくてなんか得した気分になる。 そういえば清麿って中学生だったな。すっかり忘れていた。

18:00 ぐらいになって、絆創膏を外してみる。絆創膏剥がしたて特有の白さになっている、タイピング確認をしたところ、特に痛くなく競技に支障は出なさそうで安心した。 解けていない問題をチラチラ見たりネットサーフィンをしたりして夕食までの時間を過ごした。

食後休みつつ AtCoder Beginner Contest 204 - AtCoder の準備をする。

A 問題。最近の A 難しい。$ (6 - x - y) \bmod 3 $ でいいが本番は一致する場合とそうでない場合で場合分けをした。

B 問題。$ 10 $ 個を超えている木に対してのみ $ A_i - 10 $ を足し合わせれば良い。

C 問題。$ O(N(N+M)) $ が間に合うので素直に DFS を各頂点から実行するのが良いだろう。最初双方向だと思って sample 合わなくて困った。 ちなみに、強連結成分分解をすれば $ O(N+M) $ でも解けるな。

D 問題。 $ 2 $ つに分けたときの max-min 問題。ついでに和が一定なので片方の和のみを考えればいい。よく考えると部分和 DP でいいや。 単に部分和 DP よりは和一定が本質だな。 こういう $ 2 $ 択の最適化は余程選び方にいい性質がない限り全探索ベース以外無理なの明白な気がするが、意外と貪欲を試す人が多かったらしい。

E 問題。各辺のコストが時間とともに広義単調減少するね。よって dijkstra にコスト計算を生やせば良いと思う。 $ t+1 $ が $ \sqrt{D} $ 以上になるまで待つのが最適。商の値の性質は、分子が分母の平方根以前以後で変わるというのは時々競プロで出る気がする。 分母を $ 1 $ ずつ増やしてくと平方根以前は狭義単調減少になり、平方根以後は被りながら高々 $ 1 $ 変動の広義単調減少になる。 $ 1 $ 以下の変動の時待つコストと合わせてトントンなので、結局平方根以上になるようにするのが最適だとわかる。 $ (t+1)^{2} \geq D $ の条件式を書いてオーバーフローによる WA でゲロ吐きそうになっていた。

F 問題。2x1 と 1x1 のパネルを敷き詰める方法の数え上げ。 $ H \leq 6 $ で $ W \leq 10^{12} $ だ。うーん。どう見ても DP だ。うーん。行列累乗だぁ。 ベクトルを考えると、列ごとに見て埋まっているかどうかの $ 2^{H} $ 次元で十分そう。 ただ行列の計算が下手でかなり困っていた。それぞれの状態について DFS をした。$ H $ 小さすぎるし余裕で間に合う。 あとは累乗して出たベクトルの全部空いている成分が答え。AC。

全完タイムがかなり悪かった(ペナ込みで 100:50 )ので祈りながらコンテスト終了。 どうやら perf 2211 。黄色になれた〜。

f:id:spider_0859:20210607140652p:plain:w400
黄色だわーい

黄色だまりの仲間になった余韻に浸っていたら、Div.2 の存在を忘れていた。おやすみなさい。

週記(2021/05/24-2021/05/30)

05/24 (MON)

9:00 起床。最近は月曜日の朝はのんびりしている。朝食をバタバタすることに嫌気がさしていたのでちょうどいい。 全く話は変わるが、最近剃刀負け防止のためにかなり弱い剃刀を使って髭を剃っていた。狙い通り剃刀負けはあまりしなくなったのだが、今度はあまり剃れないという事態が発生している。 仕方なく今日は久々に元々使っていたタイプの剃刀を使うことにした。あんまり綺麗に剃れるのでびっくりした。 しかし顔がヒリヒリして痛い。早く勝利を知りたい。

10:30 ぐらいに大学へ向かう。電車内で今日の典型を確認する。★3 だ。

https://atcoder.jp/contests/typical90/tasks/typical90_av

問題概要。$ N $ 問の問題が与えられて、それぞれの問題は完全回答で $ A_i $ 点、部分点が $ B_i $ である。 ある問題に取り組む時、 $ 1 $ 分で部分点を獲得することができ、もう $ 1 $ 分で残りの点数を獲得することができる。 テスト時間が $ K $ 分の時、最大で何点獲得することができるか。ただし $ \frac{A_i}{2} < B_i < A_i $ である。

太字部分のおかげでクソ簡単に解ける。まず、各問題を $ 2 $ つに分割すると、$ 1 $ つ目の問題を解いてからしか $ 2 $ つ目の問題を解けない。 一見すると取れる点数の順序が制限されて厄介だが、部分点は半分以上のため残った点数は部分点より小さい。 つまり、全ての問題は $ 2 $ つの問題に分割した上で点数が大きい方から取っても順序を違反することはない。 分割してソートして貪欲。計算量は $ O(N \log N) $。

大学について作業をするや否や昼の時間なのでケイジャンビーフチーズ&ライスを食す。

f:id:spider_0859:20210524164747j:plain:w300
ケイジャンビーフチーズ&ライスとモンスターという頭悪そうな昼食

今週は写真を撮ってみた。思いの外頭の悪そうな昼食となった。本気で月曜日はこれしか食えなくなった。

昼食をとって少しすると、ゼミが始まる。ゼミが終わる。作業をしたりプリンターやスキャナーの設定をみたりしていた。 スキャナーとかいう機械、スキャンしかできないんだからスキャンぐらいちゃんと問題なくやって欲しい。

ふと気になったので今日の典型について、過半数制約がないバージョンを考えてみる(というかなんとなく考えていたことをまとめた)。 部分点が過半数の問題をタイプA、部分点が半分以下の問題をタイプB と呼ぶことにする。 タイプA の問題は上と同じように分割して得点順にソートする。 タイプB の問題を $ 2 $ つ以上の問題を部分点のみ獲得するような解き方は得をしない。 なぜなら、部分点のみを獲得している $ 2 $ つの問題を $ i $ と $ j $ とした時に、$ \max(A_i, A_j) \geq B_i+B_j \quad (\because A_i \geq 2 B_i ) $ が成立するためだ。 さて、タイプA の問題に $ X $ 分使うことにすると、タイプB の問題には $ K - X $ 分使うことになる。

  • タイプA の分割済みの問題を得点の大きいものから $ X $ 問解く(累積和前計算で $ O(1) $ )。
  • タイプB の決め方はやや複雑。
    • $ K - X $ が偶数なら $ A_i $ が大きい方から $ \frac{K - X}{2} $ 問解く。(累積和前計算で $ O(1) $ )
    • $ K - X $ が奇数のとき部分点のみを獲得する $ 1 $ 問を選んでからそれ以外の問題について偶数と同じ処理で良い。
      • 愚直にやると $ O(N) $ かかる。
      • 部分点のみを獲得する問題が、タイプB の問題を $ A_i $ の降順に並べた時に $ \frac{K - X - 1}{2} $ 番目以内かより後ろかで場合分けする。
      • 以内の場合は $ \frac{K - X - 1}{2} $ 番目までで $ A_i - B_i $ が一番小さいものを部分点として選ぶとよい。
      • より後ろの場合は $ \frac{K - X - 1}{2} $ 番目より後ろの部分で $ B_i $ がもっとも大きいものを選ぶとよい。
      • 以上の $ 2 $ つの場合はどちらも累積 min や累積 max を前計算することで $ O(1) $ で処理できる。

以上の処理により、全体の計算量のボトルネックはソートの $ O(N \log N) $ になって解けた。と思う。

色々やっているうちにジャッジが来たので、書いて投げる。AC。制約がバージョンのジャッジも欲しい(わがまま)。 あとでランダムテストはするかも。

おやつにプリンを食べて、作業を再開することにした。 あとはいつもの月曜日通り作業したり喋ったりしているうちにいい時間になる。 今日の進捗自体は微妙だった気がするが、体調も精神状態もいいのであまりに気にしないことにする。

気分がいいので帰りにゲーセンに行ってしまう。これは完全に失敗だったが、楽しかった。 ボルテに $ 998244353 $ 人の待ちができていたため、pop'n music のリハビリをすることにした。 絶望的なまでに下手くそになっていたが、なんとかして地力を戻していきたいね(写真なし)。

この時点でクソ眠かったため今日のコドフォはパスかもなと思っていた。 帰宅する。実家ぐらしは神。ご飯を残してくれていた。感謝しながら食べると元気が出た。 眠いことには眠いが元気が出たので当然コドフォに出席させていただくことにした。 というか結局大体の場合コンテスト出たさに負けてコドフォやってしまうんだよな。

Dashboard - Codeforces Round #722 (Div. 1) - Codeforces

コドフォ惨敗した。気持ちだけが先行して脳が付いてきていなかったらしい。

A 問題。$ L_i $ か $ R_i $ 以外を選んでも得をしないといういつもの性質がある。なぜなら、中途半端な値にして場合分けして考えるとわかるが伸ばししろがあるか不変かのどちらかであることが簡単に確認できるためだ。ここでコンテスト中は脳が腐っていたため、木 DP のマージパートに $ O(2^{B}) $ ($ B $ は枝の数) と勘違いしてしまい人生が終了した。本当は着目している頂点でどちらを取るか決めれば枝達はそれぞれが独立に決まるため、$ O(B) $ でマージできる。

B 問題。これも難しかった。つかみどころがなくしばらく困っていた。パラメータが少ない定数個しかない問題は再帰的な構造が存在することを疑ってみるのがいいと思いだした。ここで $ x $ の時の答えを $ f(x) $ として改めて観察すると、一番外側をペアにするとき中の状態は $ N-1 $ と同じになり、 $ f(N-1) $ だ。同様にして外側 $ i $ 個ずつをペアにするときは $ f(N-i) $ であることが分かる。あとは、包含関係が存在しないパターンが残されている。この場合すべてのペアの距離が同じなのでよく考えると、$ N $ の約数の数だけこのパターンがある。約数の個数を前計算した上で累積を持ちながら DP をすることで計算可能。あとで思ったのだが左端をどことつなぐか考えるというアプローチも悪くなさそうだ。

C 問題。こういうの得意なはずが AB のムーブの焦りからか落とした。一つ目の木で根からの任意の頂点へのパスに含まれる頂点集合で、二つ目の木では祖先-子孫の関係が一切ない部分集合の最大値を求めれば OK。根から頂点へのパスを全探索するみたいな問題は、DFS で行きがけに追加、帰りがけに削除みたいなことをしてやるのが鉄板。当然この時は revert が可能なデータ構造である必要があるのに注意。頂点の数を最大化するため、追加した頂点で祖先-子孫の関係ができてしまいそうになった時子孫の方を残すのが常に最適である。自分の思いついた解法は、頂点追加時に遅延セグ木(双対セグ木)で部分木を頂点番号で塗りつぶす。そしてその子孫が追加されそうになった時に、祖先の塗りをクリアして改めて子孫の部分木を頂点番号で塗りつぶす、というもの。revert も自明に可能。これで解けた。今回子孫は祖先より頂点番号が大きいことが保証されるため逆パターンは考えなくてよい。

しかし Twitter を見ていると、単純に頂点を set に追加して、追加した頂点の Euler Tour 順の直前と追加した頂点を見て、追加した頂点が直前の頂点の子孫(部分木内に存在する)なら直前の頂点を削除する、で良いことが分かる。たしかに追加前が祖先-子孫の関係が存在しないことが保証されているため簡単に証明ができる。賢い。しかもこれの優れている点は上の青字の制約を満たさない木の制約の時も逆パターンが簡単に書ける。遅延セグ木で逆パターンをやろうとすると割と地獄だし定数倍重そう。

結果は爆死だったが、BC 問題で得られた経験と知見からすれば -92 は安いものだと自分に言い聞かせて寝た。

05/25 (TUE)

深夜コドフォで直後に復習じみたことをしていたため起きられるわけもなく、11:30 起床。最悪な気分になりながら朝食をとる。

大学から TA の給料振込のための講座番号を教えてもらっていないという電話がかかってくる。申し訳なさすぎる。すぐ回答する。 その後も一応ちょっとした作業をしていて、昼飯を食べる。昨日の残り物がメインだ。おいしい。

昼食後に今日の典型を確認する。

https://atcoder.jp/contests/typical90/tasks/typical90_aw

問題概要。長さが $ N $ で全部 $ 0 $ のビット列と $ M $ 個のアイテムが与えられる。各アイテムにはコスト $ C_i $ と区間の左右を表す $ L_i $ $ R_i $ が与えられて、アイテムを使うことで、持っているビット列の $ L_i $ から $ R_i $ を Flip させることができる(端を含む)。任意のビット列を作るために必要なアイテムの合計コストを求めよ(不可能なら $ -1 $ を出力)。

区間の Flip なんてものはもう確実に累積前 xor に読み替えて端と端のみに $ 1 $ が寄与していると考えるのが典型だとF - Perils in Parallelとかその他多数の問題で学んでいる。実際そうしてみると、累積前 xor の最後の要素以外の $ 0 $ と $ 1 $ を自由に決められるような集合を取れば良い。作りたいビット列が決まれば「接続行列を係数にもつ線形方程式」と同じ形だと思う。opt さんの LSI.pdf をほやほや~と思い出すと、適当な全域木を取ってきて、葉から処理して係数を追い出していくので連結成分ごとに矛盾する可能性があるのは $ 1 $ つのみである。$ 1 $ つは自由が利く今回の問題では、全域木であれば条件を満たしている。よって $ N+1 $ 頂点 $ M $ 辺のグラフを考えて最小全域木を取れば OK。

Flip の問題が累積 xor でキレイになる問題で痛い目を見た(B - Tree Edges XOR)ためこれからは一生確かめる。

そういえば、類題で tute くんの問題の No.1244 Black Segment - yukicoder を通していなかったことを思い出したのでやる。 この問題は $ M $ 個の区間 Flip が与えられるのは同じなのだが、区間 $ [A,B] $ を包含するようなある $ 1 $ つの区間内を全て $ 1 $ にしてそれ以外は $ 0 $ にすることが目標。目標を達成する最小の区間 Flip 回数を求める。累積を考えるとやはりグラフに落ちる。$ A $ 以下の頂点と $ B $ より大きい頂点の距離として最小のものを求める。これは最短距離問題なので、複数始点 BFS で解ける。当然どの始点からもどの終点にも到達できない場合は Impossible となる。提出して無事 AC。 他の人の提出を見たけど、複数始点複数終点ではなく辺を張る段階で頂点をまとめてしまう実装もあった。

今週も週末にピアノを対して練習しなかったので反省した。今日も $ 3 $ 時間ぐらいしか弾かなかった。相変わらずクソ難しいんだけど光明が見えてきた。

夕食の後、いつも通り水曜の午前中締め切りのショートレポートを書くために講義を視聴する。が、なんか今週は課題がなかった。 そのあと今週のジャンプを読む。今週で一番話が動いたのは呪術廻線かな。あとは、どう持っていきたいのかよくわからなかった野球漫画が打ち切りになりそうな雰囲気がある。呪術廻戦は結構世間的に人気らしいのでネタバレを平気な顔して書くことが憚られるな。Dr. STONE はなんかとりあえず仲間は全員復活した。死人も生き返ってしまう。すぐ打ち切られる漫画は大体方向性がよくわからないため、話がブツ切れに感じられてしまい、結果として話の大きな流れを全然思い出せないんだよな。

時間が余ったので競技プログラミングを少しやる。先週からあまり時間がとれていないので気になる。

D - 大ジャンプ を解く。 問題概要。$ 1 $ ターンに $ X $ 軸と $ Y $ 軸の正の方向・負の方向にそれぞれ $ \frac{1}{4} $ の確率で $ D $ だけ移動する。$ N $ ターン後にちょうど座標 $ (X,Y) $ いる確率を求めよ。

まず、当然 $ X,Y $ が $ D $ の倍数でなければ到達することはできない。以降では $ \frac{X}{D}, \frac{Y}{D} $ を $ X,Y $ 、$ D=1 $ として問題を解く。 メモ化再帰では $ O(N^{3}) $ ぐらいかかるなと思いマシな解法を探す。$ X $ 軸と $ Y $ 軸に問題を分割できないか考えたところ、まず $ X $ 軸方向に $ a $ 回、 $ Y $ 軸方向に $ b $ 回移動するの確率は $ \binom{N}{a} / 2^{N} $ であることがわかる。 あとはそれぞれの軸について考えると、$ a $ 回中ちょうど $ (a-X)/2 $ 回負の方向に進む必要がある。よって、$ a $ 回 $ X $ 軸方向に移動したときに $ X $ にいる確率は $ \binom{a}{(a-X) / 2} / 2^{a} $ である。$ b $ 回 $ Y $ 軸方向に移動したときに $ Y $ にいる確率も同様に求めることができ、$ 3 $ つの確率をかけ合わせれたものを全ての $ a,b $ の割り振りについて足し合わせれば答えが求まる。割り振りのオーダは $ O(N) $ で、二項係数の前計算が $ O(N^{2}) $ のため、ボトルネックは後者になり間に合う。 今回、DP も似た大きさのものの足し算だし、分母が $ 2 $ の累乗だったため誤差に強そうと思い double の上限下限のみ慎重にやって AC。ちなみに軸別に分けて条件付確率を求めなくても、条件式を連立させれば多項係数によって普通にとけそう。

05/26 (WED)

起床は 10:30 。正直もっと早く起きて散歩やランニングをしたかった。最近運動不足によって体調がおかしくなっているように思う。

週記の昨日の夜のことを書きつつ朝食を食べる。あと今日もピアノと向き合わなければならないだろう。

とりあえず今日の典型を確認する。★3 だ。

https://atcoder.jp/contests/typical90/tasks/typical90_az

問題概要。$ N $ 段の階段があり、$ 1 $ 回に $ 1 $ 段か $ L $ 段上がることができるとき、$ N $ 段をちょうど上り切る登りかたは何通りあるか。

超ベーシックな一次元 DP 。なんか最近同じことを典型90 でした気がするけど、気のせい? 気のせいじゃなかった。典型 42 で同じことをした。 遷移が $ O(1) $ で、トポロジカル順も小さい方からなので本当に素直に $ O(N) $ で解ける。 因みに、遷移が $ 2 $ つしかないため二項係数を使って経路長でループを回すことによって解くこともできそうだ。 遷移が $ 2 $ つの時は二項係数を使うことができ、高速化できる場合も少なくないためアンテナを張ることを忘れないようにしよう。

ふと埋めようと思ったので F - Graph Smoothing を解いてみる。

問題概要。 $ N $ 頂点 $ M $ 辺の単純グラフと非負整数列 $ A $ が与えられる。以下の操作を $ K $ 回行う。

  • $ M $ 辺から uniform random に $ 1 $ つ選び、つなぐ頂点を $ x, y $ としたときに $ A_x $ と $ A_y $ の値を算術平均で均す。

操作後の $ A_i \quad (1 \leq i \leq N) $ の期待値を答えよ。

$ N \leq 100 $ と小さい。こういうのは順序が大切になってしまい、寄与ゲーにすることは難しいと思われる。$ N $ が小さいので DP を考えてみる。状態数 $ O(NK) $ で遷移が $ O(M) $ の DP を簡単に思いつく。 当然これは $ K $ がデカすぎて不可能。期待値の線形性によって $ M $ 個の遷移をまとめて $ O(N) $ にすることができる。 DP の遷移が同じものを $ K $ 回行うとき、 $ K $ がデカすぎるという問題は、多くの場合行列累乗かダブリングによって解決する。 $ M $ 個の遷移行列を足し合わせて $ N \times N $ の遷移の変換行列ができる。今回 $ O(N^{3} \log K) $ が十分間に合うので行列累乗したものと最初の $ A $ ベクトルを掛けることで $ K $ 回行った後の $ A $ の期待値が計算できる。

この回の ABC では DE で実装に失敗しまくりパニックになっていたから F が難しく見えたが、全然そんなことはなかった。 さて、作業をしなければならないのでしばらくは作業をしている。今日はやることが多くて SRM を見送ることになりそうだと思った。 作業内容はちょっと話せないのでスキップさせて頂く。

さて、ちょっと競技プログラミングでもやってリフレッシュしようと思い、F - Minflip Summation 開く。最近当日 AC できなかった ABC-F の埋めをさぼってしまっているため消化の意味合いもある。

問題概要。$ 1 $ と $ 0 $ と $ ? $ からなる文字列 $ S $ が与えられる。これを $ K $ 個連結したものを $ T $ として、$ ? $ の部分は $ 0 $ にも $ 1 $ にもなり、すべての $ ? $ を $ 0 $ か $ 1 $ に書き換えた後の文字列を $ T' $ とする。全ての $ T' $ について、全ての文字を同じにするのに必要な区間 Flip の最小回数を求め、和を答えよ。

測らずも昨日の典型と被っている (区間 Flip という点で)。例に従って累積前 xor を考えてみる。累積前 xor の世界では区間 Flip $ [i,j] $ は $ i $ と $ j+1 $ の $ 2 $ つの位置を Flip する操作になる。 よく観察すると、結果はランレングス圧縮したサイズを $ M $ として $ \left \lfloor \frac{M}{2} \right \rfloor $ となる。 整数集合 $ S $ を与えたとき、 $ cnt(i) $ を $ S $ の要素で正定数 $ A $ で割った余りが $ i $ であるものの数とすると、

$$ \sum_{x \in S} \left \lfloor \frac{x}{A} \right \rfloor = \frac{ \sum _ {x \in S} x - \sum _ {i=1}^{A-1} i \cdot cnt(i)}{A} $$

は明らかである。今回の問題では $ A=2 $ でこの変形をすればよく、$ T' $ をランレングス圧縮したサイズの集合を $ U $ として

$$ \sum_{M \in U} \left \lfloor \frac{M}{2} \right \rfloor = \frac{ \sum _ {M \in U} M - cnt(1)}{A} $$

と書ける。実は $ cnt(1) $ は簡単に求められる。なぜなら、$ T' $ の先頭と末尾が同じパターンの場合の数であるからだ。ただ $ S="?" $ であるときに注意したい(このケースで無事に WA をもらった)。

$ \sum _ {M \in U} $ を求めるのには、各隣接のランレングス圧縮したサイズへの寄与を考えればよい。$ 01 $ か $ 10 $ になっていれば $ 1 $ 寄与している。基本的にはこれを $ K $ 倍すれば良いが、連結しているため先頭と末尾の隣接も $ K - 1 $ 回分考えなくてはならない。 よって上の式をそのまま計算することができ、$ O(N) $ で解けた。

因みに行列累乗で解くこともできる。こういう時も行列累乗を思いつける柔軟な思考を持っていたい… 木曜日は早く家を出るため頑張って寝る。というか SRM 出ないのだから本気で寝た。

05/27 (THU)

6:30 起床。いつもどおりに身支度をして家を出る。 今日は意識があったため、行きの電車の中で典型を確認する。★5 だ。

https://atcoder.jp/contests/typical90/tasks/typical90_ay

問題概要。$ N $ 個の品物があって、ちょうど $ K $ 個選ぶことを考える。各品物の値段は $ A_i $ 円 $ (1 \leq i \leq N) $ で、値段の合計が $ P $ 円以内になるように買いたい。 品物の選び方の通り数を求めよ。

なんだかナップサック問題 Like な設定だ。こんなものは効率的なアルゴリズムがあるはずがないのでいつものだろう。 制約を見ると、$ A_i, P $ がアホみたいにデカく、$ N \leq 40 $ だった。 こんなものは半分全列挙だと思い、終了。

大学につく。木曜日なので 1 限を大学で受けている。今日の課題も問題なくできそうなので安心。 しばらく作業をする。最近大学での作業で混乱していて停滞していたため、考察用紙にまとめて整理したらだいぶ見通しが良くなった。

昼飯を食べる。来週はタンドリーチキン丼を食べないと言っていたにもかかわらずキッチンカーの前にきたら口が勝手に動いていた。馬鹿。

明日の輪講発表のスライドができていないため、ミーティングが終わり次第帰宅してスライドを作成する。 自分が発表に選んだ論文が思いのほか読みにくかったことを思い出す。最悪である。 どうスライドにしたらよく伝わるかイマイチわからないままよくわからないスライドが錬成されてしまった。

さらっと言っているが、夕食の前後はずっとしょぼいスライドのために時間を使っていて、そのまま寝た。 そのためまじで書くことがない。と思ったけど、 1 問だけ競プロの問題を通していた。

F - Insertion Sort

最近の ABC-F だが、コンテスト中にいいところまで詰められたにもかかわらず落としてしまった問題だ。 問題概要。長さ $ N $ の順列が与えられる。これを昇順にするために $ 3 $ つの操作を行える。

  • コスト $ A_i $ を払って $ i $ 番目の要素を好きな位置に移動させる。
  • コスト $ B_i $ を払って $ i $ 番目の要素を左端に移動させる。
  • コスト $ C_i $ を払って $ i $ 番目の要素を右端に移動させる。

こういうそのままでは余りにもつかみどころがない問題は、緩い決定をすると見通しが良くなったりする。 それぞれの要素について、動かすかどうかを決定したと考えてみる。 動かさないものは少なくとも昇順である必要があることは明らかである。また、動かすものは数字の大きさによってかかるコストが確定できそう。 具体的には動かさないものの最大より大きければ $ \min(A_i, C_i) $、動かさないものの最小より小さければ $ \min(A_i, B_i) $ のコストかかりそう。

コンテスト中はここまで来て、要素の小さい順のいわゆるソート DP をすれば最後に動かさなかった要素の index を状態にもつ二次元の DP でできるなあとぼんやり思ったまま時間が終了した。 実はよく詰めると in-place DP のセグ木高速化のテクニックで $ O(N \log N) $ になることがわかった。 いやー筋が悪そうには見えないんだから、ちゃんと DP 高速化を考えればよかったなと思った。 そもそも元々貰う DP が苦手なため in-place DP のセグ木高速化が全然見てないんだよね。参っている。AC。

05/28 (FRI)

9:30 ぐらい起床。前回の輪講発表はスライドに致命的な間違いが存在していた反省から、ちゃんとスライドを見直す。 結構真剣にこれをやっていた。また、終わった後も普通に作業をしていて全然ここに書ける内容がなくて助けてほしい。

諸々終わって今日の典型を確認する。★3 だ。

https://atcoder.jp/contests/typical90/tasks/typical90_az

問題概要。$ N $ 個のサイコロと $ 6 $ 面に書いてある数字が与えられる。全てのサイコロの出目の組み合わせについて、$ N $ 個の出目の積の総和を求めよ。

当然そのままでは計算量が爆発していて、積の総和を式にしてみると、和と積には分配法則が成り立っているため結果的にそれぞれのサイコロ内の数字の和の積になる。 こういうのは寄与か分配法則を用いたいい漸化式が書けると相場が決まっている。

ゼミ発表がある。発表をする。またキョドってしまう。 日本語スライドだと見ながら何を話そうとしていたかが動的に追えるが、英語スライドだと自分が何を言おうとしていたかを十分思い出せないという問題がある。 これを解決するために、発表する前にどこで何を話すかを確認しておいた方が良さそう。 自分の発表が終わって人の発表を聞く。 ゼミが終わる。

ゼミが終わったので典型を AC しておく。このあとはだらだら漫画を読んでいた気がする。 適度な頻度で自分が読んでいる漫画についてこの週記に記録してもいいかもしれない。気が向いたら記録をしてみる。 ネタバレに気を使った方がいいかなとか思うと感想を入れることができないのだが、まあこんな週記を読む人も多くないしいいかも。

夕飯を食べた後、なぜか寝てしまう。夕飯の直後に横になるのは危険であることはよく知られているので反省。 起きたら Div.2 まで 2 分だったのでさすがに間に合わないと思い、諦めた。 その後 Streak をつなぐ虚無の作業をして就寝。

05/29 (SAT)

10:30 起床。朝食を食べる。今日は鬼のように体の調子が悪い。 今日の典型を確認する。★7 だ。

https://atcoder.jp/contests/typical90/tasks/typical90_ba

問題概要。インタラクティブだ。極大値を $ 1 $ つだけ持つような隠された配列がある。 $ 1 $ 回のクエリでは配列の $ k $ 番目の要素の値を得ることができる。 $ N \leq 1500 $ の制約で、$ 15 $ 回以内のクエリを用いて最大値を求めよ。

典型初のインタラクティブである。この制約では極大値=最大値なので、まず思いつくのは隣接差の二分探索である。 離散の極大値探索においては、隣接差の二分探索が優れている。なぜなら極大値の $ 1 $ つを取りたいようなシチュエーションでも壊れないためである。 また収束速度もやや速いはず。特にインタラクティブの場合はわずかな収束速度の違いもクリティカルになったりするので大切かも。

ここまではいつものインタラクティブだ。しかし、このままでは $ 2 \log _ {2} N $ ぐらいの回数がかかり、これでは満点がもらえない(最悪 $ 22 $ 回ぐらいかかる)。 ここで前の結果を再利用する極値探索アルゴリズム、黄金分割探索を思い出す。 こいつは黄金比の分割で三分探索みたいなことをすると、どっちを捨てても次の必要な値の片方は再利用によって求められるというもの。 離散関数でやる場合は定義域の値の幅をフィボナッチ数になるようにすることによってフィボナッチ数の分割によって同じことができる。 $ 17 $ 個目のフィボナッチ数が $ 1576 $ のため、注意してやるとギリギリ $ 15 $ 回のクエリ以内で最大を求めることができる。

体調が悪いのでガチでだらだらしていた。とはいえちょっと作業したりはしていた。後は漫画を読んでいた。 『その着せ替え人形は恋をする』を読んだが、面白いかも。ちょっとエッチだけど、最近の漫画はこんなもんなのかな。僕にはわかりません。 最新刊を待つまでの間にまた新しいものを読み始めるため、破綻しそうになっている。

21:00 から ARC があるので頑張ろうと意気込む。

NOMURA Programming Contest 2021(AtCoder Regular Contest 121) - AtCoder

A 問題。露骨にひっかけに来ている感じがしたので慎重にやる。 問題は $ N $ 個の二次元点のチェビシェフ距離の $ 2 $ 番目に大きいものを求めるというもの。 $ X,Y $ 座標でソートして端と端、端と端から一個動いた場所の差を計算してそのうち $ 2 $ 番目の値を出すと壊れる。 なぜなら、同じ組に対しての値が存在する可能性があるためだ。そのため、そこの重複に気をつけて丁寧にやる。AC。

B 問題。$ 3 $ 色のわんこが合計 $ 2N $ 匹いて、ペアを組んだときに色が違う時に、$ |a_i-a_j| $ だけ不満度がかかる。 不満度の合計の最小を求めよというもの。 ちょっと考えると、全ての色のわんこが偶数匹ずついたら $ 0 $ になるとわかる。 奇数匹の色がある場合を考えると、合計が偶数匹なので、奇奇偶 のパターンしかない。 ここでコンテスト中は大喜びして、奇数の色どうしで最も不満度が小さいペアを出して答えにした。 WA を貰う。ここで胃が爆発しそうになりトイレに行くが、推移的なペアを組むことがあり得ることに気づく。 トイレから駆け出して AC。

C 問題。基本的に $ 1 $ から(左から)埋めていきたい。しかし、パリティの制約があるため難しい。 状況をよーく洗うと、左側の正しい部分を壊さずにパリティ合わせをすることがすることが可能になる。 パリティ合わせを壊してしまい、何回か余計なペナルティをもらいながら AC。

D 問題。わからん。

E 問題。D よりは解けそうな気がしたが、難しい。後日また考える。

というわけで ABC 3 完。perf 2128 なのでセーフだが、C の回収が遅すぎるせいで E に時間を回せなかったのが痛かった。

体が体なので本日の活動を終了する。

05/30 (SUN)

超眠い。10:45 起床。朝食を食べる。 昼飯を食べに家を出ることになる。ついでにゲーセンに行く。

3 クレぐらいしかやってないが大満足した。Sailing Force [MXM] 9988 UC が出て、ランキングを見たら今作 30 位以内ぐらいのスコアだった。 さらっと ECHIDNA [MXM] も一発で PUC 出ており、なんかすごいよかった(適当)。

f:id:spider_0859:20210531140825j:plain:w300
ECHIDNA [MXM] PUC

f:id:spider_0859:20210531140701j:plain:w300
Sailing Force [MXM] 9988 UC

昼飯を食べに行く。デニーズに入る。オムライスとポテトとパフェを頼んだ。全然そんな気はしなかったのだが、重かったらしく帰ったらぐったりしていた。

f:id:spider_0859:20210531141040j:plain:w300f:id:spider_0859:20210531141049j:plain:w300
昼飯たち。美味しかったが重かったらしい。

家に帰って胃が復活したら、しばらくやるべきことを処理し続けていた。気がついたら夕食を食べ終わって ABC の時間になっていた。 今日は黄色コーダーになれるかどうかがそこそこかかっているため、ちょっと緊張した。

AtCoder Beginner Contest 203(Sponsored by Panasonic) - AtCoder

A 問題。難しい。考えてる時間が惜しいので if 文を三本書いた。

B 問題。言われた通りの数字を愚直に足し上げるだけ。

C 問題。適当にやりすぎると、間に合わないので丁寧なタイプのシミュレーションをする。 こういうのにもだいぶ慣れてきた気がする。

D 問題。最初は座標圧縮した上で分布を考えてうまく差分更新できないか考えていた。 $ O(N^{3}) $ 以上は少なくともかかりそうで方針を変えようと思った。そういえば中央値の最大化最小化は決め打てば分布の値が $ 2 $ に落ちるんだった。 よって二分探索を使って $ O(N^{2} \log N) $ をする。AC。この時点で $ 100 $ 位を切っていたので緊張。

E 問題。問題文に沿って遷移を考えると、ある $ Y $ 座標にいけるかどうかを考えながら $ X $ 方向に進んでいくみたいなことにすれば良さそう。 ただ座標の幅が広いのでそのままはできない。$ N $ から隣接する黒色だけ考えれば良いから最悪でも $ M+1 $ の幅だけ考えれば良い。 $ X $ 方向に進んでいくと黒が存在したらその時点で $ Y $ 座標隣接のどちらかがに到達可能であった場合、黒の $ Y $ 座標に到達可能にする。 よく考えると、これは $ M $ 回しか行われないため、in-place にやれば間に合う。 完全に実装方針を間違えている。死ぬほど時間をかけながら AC。この時点で F を通さなければ黄色になれなそうなことに気づきくそ焦る。

F 問題。焦りから残した数の最小と最大の比を最小化すれば良いと思ってしまう。 ゆえに残しは区間になり $ \left \lfloor \frac{a_{i+(N-K)-1}]}{a_i} \right \rfloor $ の最小値が高橋くんの操作回数だと思い込んでいた。 何もかもが間違っている。これでは通らない。だめなことに気づいたのは終了の 5 分前だ。 DP でできそうなことにコンテスト後に気づき、解ける。黄色になれなかったため声出た。

Codeforces に出る。Combined だ。 不快感がかなりあったのでここではあまり触れないが、問題文に補足が追加された時に題意は変わらないはずと考えるのは当然じゃないか? 題意が変わらないと考えた結果、完全に混乱して時間を浪費してしまった。結果普通に題意が変わっていた(おそらくは writer の条件書き忘れ)。

いや、題意が変わったならアナウンスにそれをちゃんと書いてくれないか?「条件を書き忘れていました。すみません。」ぐらいせめて書いてくれよ。 競プロなんて問題文が正しいことが保証されて、競技者の信頼の上に成り立ってるんだから writer を疑ってくれというのはクソすぎないか? 俺は競プロがやりたいのであって、writer の気持ち当てコンテストがやりたいわけではない。 なんか間違ったこと言ってますか?このまま rated でも良いけど、今後はこういうのやめてほしい。やめてほしいから煽り気味にお気持ち表明 Comment した。

不快感にのまれながら就寝。