むかでのチラ裏

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

週記(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 した。

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

週記(2021/05/17-2021/05/23)

05/17 (MON)

睡眠時間が短すぎて、9:00 には起きていたが半寝状態で 10:00 ぐらいまで何もしなかった。起き上がれたため、大学に向かう。 そんなんで眠すぎる故、行きの電車は何かをチェックしたり考えたりすることなくひたすら寝ていた。

大学に着くと、昨日の分の週記を書き上げて初めての週記を投稿する。妙な達成感がある。 それはそうと昼飯は月曜日のキッチンカーであるところのケイジャンビーフステーキチーズ&ライスを食べた。寝不足には重かったが美味しかった。来週こそは写真を撮ってここに貼ろうと思う。

ゼミが始まる。この時期の月曜は B4 の輪講(例年同じやつ)なので聴きながら裏で作業したりすることが多い。 作業をしようと思ったが、今日の典型を確認していないことに気づいたので先にそちらをチェックする。

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

正整数 $ K $ が与えられて、10 進数での桁和が $ K $ かつ、その数そのものが $ 9 $ の倍数であり、さらに $ 0 $ を桁に含まないような整数を数え上げろ、という問題。

$ 9 $ の倍数である事と桁和が $ 9 $ の倍数である事は同値である事はあまりにも有名。というかまあ式を書けば一瞬で確認できる。 $ N $ 進数における $ N-1 $ の性質だと思う。 つまり、$ K $ が $ 9 $ の倍数でないなら答えは $ 0 $ であり、$ 9 $ の倍数ならば二つの条件は自然に満たされる。あとは $ 0 $ を含まないように整数を構成するだけだ。 これは $ 1 $ 回で $ [1,9] $ マス先に進める時の $ 0 $ マス目から $ K $ マス目までの経路数に等しい。普通に DP をするといい。更新の時に区間加算をするので高速になるが今回は遷移が多くないので愚直でも問題ない(というか $ 9 $ ならキャッシュとか考えて絶対に愚直の方が速いだろう)。理論上は線形探索は悪だが、実際はシーケンシャルな処理なので相当キャッシュとかが効いてある程度まではむしろ高速だよねという話題、あまり競技プログラミング界隈では聞かないな。

ゼミも終わり、一頻り喋ったりしたあと作業に戻る。作業の途中で典型のジャッジが来ていそうなので提出する。$ K \bmod 9 \neq 0 $ の場合に $ 0 $ を出力するのを忘れていて WA をもらう。書き直す。AC。 先週の金曜と土曜の典型をまだ書いていない。なぜなら最大流ライブラリをまだ書いていないためである。いやその理論だと土曜のは書けるな。 アルゴリズムもわかっているしなんなら空で書くことができると思うんだけど、どうせ書くなら綺麗にしたいため中々面倒くさい。

そういえば今日も途中で大学に入っているセブンへプリンを買いに行った。なんか毎週同じことをしている気がする。 大学に入ってからというもの一週間スパンでループをしているような気がする。社会にでたらもっとこれになるのかと考えたら尚更社会に出たくなくなってきた。日常に刺激がないと死んでしまうため。

ところで今作業がほぼほぼ調べ物フェーズなんだけど、全然出てこない。競プロの知見とかって死ぬほどよくヒットするけど、研究に必要な知見はゲボほど出てこなくて発狂しそうになる。 調べ物といえば先週ローカルに落とすかと言っていたチートシートはまだ落としてなくて $ \bmod $ を出すためにまたググってしまった。

なんか取れたデータが壊れていそうな気がしたが、もう燃料切れなので帰宅する。 帰宅して晩飯を食べて、もこうの最新動画を見て、ジャンプを読んだら日付変更まで 30 分を切っていた。 もこうが全然使われないポケモンを使って興奮している動画を見るのが好きなんだよな。 ジャンプは Dr. STONE でようやく千空が復活した。一言でコメントできるのが Dr. STONE ぐらいしかない。

伝説の害悪戦法「レベル1ココドラ」を完全再現してみたwwww【ポケモン剣盾】 - YouTube

例によって例のごとくこの時間に競プロをやろうとする。いい加減もう少しマシな時間にやる人間になりたい。 とりあえず最大流ライブラリが必要ない典型 41 の実装をすることにした。

凸包を求めるアルゴリズムを完全に忘れている。まあライブラリがあるからいいと言えばいいが、ソートして凸になるように上半分と下半分に分けて構築するだった気がする。多角形は反時計回りの順序の点の列にするため、最後の $ 2 $ 点と次に追加する点の関係がちゃんと反時計回りになっているかチェックして、なっていなかったら最後の点を削除、という操作を繰り返すと下半分が構築できる。上半分はソート逆順にやることで構築できる。最も左下と最も右上の点は絶対に凸包に入るので簡単に証明はできたはず(はず)。久々に書くと意外と面倒。自分の幾何ライブラリを見ると汚くてびっくりする。

典型 41 の解法自体は先週の週記に書いたので割愛する。今日は完全に寝不足なのでここで活動終了。

05/18 (TUE)

12:00 起床。かなり身体のダルさが取れた。今日は普通に活動ができそうだ。 正午まで寝ていたことがバレて親父がヒリついていたことを除けばかなり良い滑り出し(10 : 0 で僕が悪いのでかなりつらい)。 今日の典型を確認する。

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

二次元グリッドが与えられる。マスの種類は '#''.' であり、それぞれが壁と空間。壁を通ることはできない。スタート地点とゴール地点が与えられるので、スタートからゴールまで行くとき方向転換の回数の最小値を求めよ、と言う問題。

この問題は過去に何度か見たことがある気がする。普通のグリッド上の位置の状態をさらに $ 4 $ つの向きによって分割する。これで向きが変わる遷移について $ 1 $ 、そうでない遷移について $ 0 $ に設定した最短経路問題になる。この制約ならグラフを陽に持たなければ dijkstra 法で耐えるかもしれないが、まあ 01BFS をすればいいだろう。解説のキーワードは「追加の情報が必要な場合は頂点を倍加する」みたいなのだろうか。 ケアするポイントとしては最初の移動による方向転換だろうか。自分は始点に上下左右すべてぶち込んでやった。

ここでとんでもないことに気づく。自分の 01BFS が壊れていた。具体的に実装を見ると一回到達した頂点への距離更新が行われない実装になっていた。え、これを使って問題を通したことある気がするんだけど…と思ったけど、$ 0 $ の辺を先に全て隣接リストに入れれば壊れないためだな。かなりタチが悪いバグの残り方だな。直して push や。

時系列が前後するが、実装をする前に昼食をとっていた。昨日の残り物を食した。あと食べかけのコンビーフを処理した。 実装が終わったあとは、ジャッジ来てるかなと思って確認をしたが来ていない。とりあえず週末普通に競プロに力を入れすぎたため少しピアノを弾くことにした。

3~4 時間格闘をしていた気がするが、下手くそすぎてブチ切れそうになった。才能がまるでないように感じられるデーだった。競プロや音ゲーにもたまに訪れる日が今日だったようだ。脳血管が切れそうになったので切り上げて部屋に帰ってクーラーで涼んだ。 弾くときに楽譜が暗くて見づらくならないようになどの理由から白熱灯のライトをつけるのだが、これを弾きながら浴びるとクソ暑い。その部屋のクーラーがまだ使える状態でないためうっかり溶けてバブルスライムになりそうになっていた。

ジャッジが来ているか確認した。流石に来ていた。186ms だった。dijkstra 法でやると落ちる可能性が十分ありそうだ。グラフのサイズは最大で $ 1.6 \times 10^{7} $ ぐらいあるのでまあそれはそうか。

夕食の時間になったので、夕食をとる。チーズ入りチキンカツが美味しかった。というか気づいちゃったんだけどチー牛野郎なのでチーズが好きなんだよね。

夕食の後の一時間ぐらいは Twitter を見たり、ネットサーフィンをしたりしていた。 今日の典型をグラフを陽に持って 01BFS をやるとどのぐらいなんだろうと思って試してみた。1 sec 以上かかっていた。これは dijkstra はかなり厳しいんじゃないか?

明日の 10:45 提出の小レポートがある。今週は週末を自由に過ごしすぎたため、まずはシステムに上がっている講義音声を DL して聞く必要がある。今週はすべての音声ファイルが壊れていなくて安心した。この講義は大学院の講義の癖に全然専門じゃないし、専門的なこともしないため完全に学部生時代の一般教養科目を受けるのと同じテンションで参加している。社会勉強になりますみたいな。 講義音声を聞き終わり、レポートを書いて提出する。週ごとに 400 字前後の目算がうまくなる。

CLIST を確認する。二日後にコドフォの Div.2 があるらしい。いい加減、薄橙にもどらないと恥ずかしいように思ってきた。 そのためにも精進や。とりあえず、最大流のライブラリを作って verify して典型 40 を通すことにした。もういい加減盗人をやめたい。 その理論で行くと beats もそろそろ自分で実装した方が良いかもしれない。まあそれはまた今度…

05/19 (WED)

なんか知らないうちに寝落ちをしていた。11:00 起床。朝飯代わりの何かを口に突っ込む。 少し作業らしき何かをしていたが、間もなく昼食をとることになる。親子丼を食べた。かなりおいしい。

ピアノの日なので、手ならしをするために食後は出かけるまで弾いた。今日も下手くそだ、助けてくれ。 というかそろそろ気づいちゃったけど、これ俺が下手くそなのもあるけど単純にラ・カンパネラが難しい。 完全に暇な週とかがあったらみっちり練習したいが、大学に行く日は練習ができなかったりしてかなり困難だ。

レッスンから帰ってきた。そういえば今日はバタバタしてまだ典型を見ていないことを思い出す。最大流を Ford-Fulkerson と Dinic の両方で書いてリポジトリに push する前に、今日の典型から片づけてしまおう。

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

今日の典型は、長さ $ N $ の整数列 $ A $ と以下のようなクエリが $ Q $ 個与えられて、それを処理しろというもの。

  • $ x $ と $ y $ が与えられて、配列 $ A $ の $ x $ 番目の数と、$ y $ 番目の数をスワップする。
  • 配列全体を一つ右シフトする。一番右の要素は一番左に来る。
  • $ x $ が与えられて、配列 $ A $ の $ x $ 番目の数を出力する。

最近の ABC でよく見るやつだ。実際に愚直にシフトすると間に合わない (平衡二分木を貼るのもまた一興だが…)。現在のシフト幅を持ってさえいれば $ x $ 番目の要素を見つけるのは簡単である。これを管理しながらクエリを一個当たり $ O(1) $ で処理できて OK。 雑に実装すると、剰余の演算が多くなる。割り算は(ある意味で当然なのだが)他の四則演算と比べて滅茶苦茶遅い。案の定 400ms とか返ってきてワロタ。掛け算をおこな三項演算子で書きなおす。71ms になる。

このタイミングで兄が部屋に入ってきて星野源新垣結衣の結婚ニュースを見せてきた。ワロタ。これは絶対に Twitter の人々は大騒ぎだろうと思ってみたら大分楽しい感じになっていた。星野源前川みくP なんですよね。現場からは以上です。

最大流のライブラリの作成に戻るが、インターフェースをどうしようか迷っている。構築問題で最大流を使うときに流量とかを知らなきゃいけないと思うんだけど、そこら辺のケアが一番面倒くさい。付加的な情報を辺に載せたいことがあるため、struct Edge みたいなものをユーザ定義にする(最もベーシックなやつは用意しておく)みたいなことをするのが良いかもと思ったが、逆辺を張るのをユーザ負担にするのは結構つらそう。インターフェースのことを考えていたら頭痛くなってきた。脳死で常に復元が出来るような辺を持つことにした…。

結果的な実装としては、辺のインデックスを任意に入力することを諦めて張った順番にインデックスを振る。辺インデックスに対応する始点と隣接リスト中の位置を覚えておいた。これをすることで辺インデックスの管理はユーザ負担となるが、代わりに辺の容量と流量を変更したり取得したりするのが簡単に $ O(1) $ で実装できるのでこれを採用。よく考えると ac-library と似たようなインターフェースになっている気がする。 メモリを余計に食うような気も一瞬したが、結局インデックスを辺に載せると辺を張る際に、逆辺と併せて int $ 2 $ 個分のメモリを消費することになるが、視点と隣接リスト中の位置を覚えるのも同じ量のメモリ消費なので変わらない。 復元に使わなそうな辺にインデックスを振らないようにできるように add_edge 関数をしようかとも思ったが、わざわざそんなことを気にする方が大変そうだと思った。

間に夕食を食べたりしながら納得のいく最大流ライブラリが完成した。実は Dinic を書くのが初めてだったのだが、この実装を見て DFS 途中で抜けて途中から再開するみたいな書き方があることを知った。これからの実装方針の糧にしたい。 最小費用流のライブラリも作ろうと思ったがなぜか一般グラフの最大マッチングアルゴリズムに関するスライドを読み始めてしまう。

https://www.dropbox.com/sh/7uhazzp6wvx9mi7/AACpEgmn--Grp9nVD3NOD9Hia?dl=0&preview=%E8%AC%9B%E7%BE%A9%E8%B3%87%E6%96%99.pdf

ふむふむなるほどと言いながら書いていたら夜中になっている。完成はしなかった。あともっと速いやつもあるらしい。いずれにしても一般グラフの最大マッチングについてまた今度にした。

05/20 (THU)

6:30 起床。起床時間の波がえぐすぎる。諸々支度をしてジャムサンドみたいなものを食して大学へ向かう。 家を出た時は全然眠くなかったのに、電車に乗っているうちにクソ眠くなってくる。最終的に典型を確認するのが億劫になるぐらい眠かった。

9:00 からのオンライン講義を受ける。眠いが、そんなに難しい内容ではないため耐えている。というか大学院の講義は意外と適当だ。 多分だけど大学院生の活動のほとんどが研究だからだろう。そんな感じで講義をそつなくこなす。 眠気もマシになってきたので、今日の典型を確認する。

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

二次元平面上の点が $ N $ 個与えられて、$ K $ 個のグループに分ける。分けた時にグループ内の最大の $ 2 $ 点間距離を最小化せよ。距離は二乗で答えろ、という問題。

うーん、とりあえず $ N \leq 15 $ のため、全ての任意の点集合について最大の $ 2 $ 点間距離を時間内に求めることができる。 そこで bit DP をすれば $ O(K 3^{N}) $ でできそうである。具体的には、点集合ごとに取っていくことを考えて $ K $ グループ以下選んでその最遠距離の最大を求めればよく、被りのない点集合のみを選んで遷移すればこの計算量でいける。これ、間に合うのか?わからない。間に合って欲しいので考えるのをやめた。

競技プログラミングばかりやるわけにはいかないので作業をやる。全然身に入らない、眠すぎる。おかしいぐらい眠い。胃も今年度最悪のコンディションになっている。本日は営業不可能ということらしい。マジでメンタルも終了しそうになるが、人と会話して元気にはなった。ところで今日の昼はタンドリーチキン丼だった。写真を撮ることを毎度忘れる。胃が最悪なこともあって重いがうまい。

そんなこんなで何も捗らないまま家に帰って夕飯を食べる。食後も普通にボケーっとしていた。今日は 2 時間どころが 1 時間すら集中できないことが明らかなので、コドフォ Div. 2 をやらないことにした。「やらない」って宣言してからずっと「やっぱやろうかな・・・」みたいな気持ちになるの本当に勘弁してほしい。

活動が厳しい日で、書くことがあまりないため現在読んでいるマンガの話でも記録しておこうと思う。今「ハリガネサービス」と言うマンガを読んでる。バレーボールの漫画なんだけど、結構好み。作者がキャラクターを大事にする作品に弱い。構成は一般的なスポーツ漫画とそう違わないように思う。もしこの週記をを読んでいる人がいて、興味があったら是非どうぞ。

05/21 (FRI)

12:00 起床。頭はかなりスッキリした。今日は十分に活動ができそうだ。朝食を食う時間がもう残されていないのが残念だが。 昼食をとる。カレーだ。うまい。結局今週も一回も食事の写真を撮らなかった。 古畑任三郎の話などをしていた。田村正和が亡くなったのでまた再放送をやるらしいので見ようかな。

昨日の典型を通さないまま寝たため、昨日の考察の通りに $ O(K 3^{N}) $ の実装をする。怖がりなので生配列を使ったり、in-place にしてメモリ消費もできるだけ少なくしたりした。部分集合を列挙する bit のテク久々に書いた気がする。提出。AC。271ms だった。余裕じゃん。自分は結構厳しめに計算量を常々見積もってしまっている節がある。気を付けていきたい。

きよしくんのツイートを確認したら、彩色数に落ちるらしくてこれによって底が $ 2 $ になるらしいな。まあ(そもそも彩色数自体が)難しいので今はパスや。なぜならこういう問題で底の $ 2 $ と $ 3 $ の区別をつけるのは極めて難しいと思うため。

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

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

$ 3 $ つの長さ $ N $ の非負整数列 $ A,B,C $ が与えられて、$ A_i + B_j + C_k $ が $ 46 $ の倍数になる $ (i,j,k) $ の組を数え上げろ、と言う問題。流石に見た瞬間かな。 $ 3 $ つの数列の各要素を $ 46 $ で割った余りを考えてそれぞれ分布を作る。あとはできた三つの分布を畳み込めばいい。普通に三重ループでも間に合うので今回はそれで実装した。普通に FFT を二回とかでもいいはず。早めにジャッジが来ていたので提出。AC。どうせ入力がボトルネックになって高速化を実感できないため速くはしなかった。

そういえば結局典型 40 を通していないことを思い出した。最小カットを意識する辺張りが簡単になるなぁを実感。Dinic と FordFulkerson 両方試す。それぞれ 9ms と 73ms 。Ford Fulkerson はワンチャン間に合わないかなと思ったが杞憂だった。

時計を見てゼミの直前だった。あぶね~と思ったがアウトだった。時々自分の部屋の時計は本当の時刻を示さなくなるのだが、それだった。二個時計があるのに全てが壊れるってなんや。稼働率の期待値計算壊れてないか?反省したのでちゃんとリマインダーを使うことにする。

ゼミが終わる。一般グラフの最大マッチングはとりあえず置いておき、最小費用流のライブラリを作ることにした。そもそもようやく自分のライブラリを作ろうと決心をした理由が GCJ で最小費用流が出題されたからである。自分は単純なので借り物のライブラリだと余りモチベーションが湧かないし、アルゴリズムが分かっていても具体的な実装を自分でしていないと弄れないし気持ち悪くて無理なのだ。どうしても使わなきゃいけない時のみこっそり人様のものを借りていたが、そんなんでは演習ができないため自分のものを作成することにした。あと結構大きい理由は、人のフローのライブラリって復元のためのメンバが用意されていなかったり、用意されていても自分に合わないインターフェースだったりする。ここが自分の納得のいくものにできるのは大きい。

とりあえず書き上げた。verify してない。

05/22 (SAT)

12:00 起床。最近睡眠習慣が崩壊している。体調は悪くない。朝食を軽くたべる(すぐ昼食のため)。 しかし、今日は一ミリも何をやる気も起きなかった。

ほどなくして昼食を食べる。マックを食べた。マックではいつもダブルチーズバーガーとチーズバーガーを両方たべる。トリプルチーズバーガーが常設されればこんな妖怪みたいなことしなくて済むのになあと思ったりもする。

本気でやる気が起きないのでしょうがなく蟻本でも読みなおすかと言う気持ちで、蟻本を読んで演習問題を解いたりしていた。POJ の C++旧石器時代なのがかなりストレスフルなことを久々に思い出した。アレ C++ じゃなくて C+ ぐらいだろ。

不機嫌な気持ちになったりしながら演習をしていて、油断して一瞬横になったのが仇となり夕飯の時間まで帰らぬ人となった。 夕飯を食べた。寝起きで食べたせいで胃が爆発しそうだ。

完全に自業自得なのだが胃にばくだんいわを抱えた状態で AISing Programming Contest 2021(AtCoder Beginner Contest 202) - AtCoder に出ることになった。脳みそ自体はそれなりに正常に動いているはずなので大丈夫だろう。

A 問題。$ 21-a-b-c $ python で送れば FA も狙えそうな問題だった。

B 問題。たまにある数字の $ 180 $ 度反転だ。幸いにもひっくり返すと Invalid になるような文字がなくリバースして $ 6 $ と $ 9 $ を入れ替えるだけ。

C 問題。ここにきて胃のばくだんいわのせいで冷静さを書いてしまう。$ i $ か $ j $ を固定すればいいのだが、脳を使わずにヒストグラムとっていじいじしてなんか合ったで提出した。$ 5 $ 分ぐらいかけた気がする。

D 問題。ばくだんいわメガンテを唱えてしまった。マジでわからないと思い唸っていた。仕方なく a を $ 0 $、 b を $ 1 $ とみなすことで整数として扱うことができて、辞書順は普通に昇順になる。よって二分探索で桁 DP をすればよかった。実際は二項係数を使って手前から貪欲に埋めていくことができる。 ヤバすぎる。

E 問題。木のクエリと聞いて HLD を貼る準備をした。思ったより不思議な条件だなぁと思っていたが、根への最短パス上に $ U_i $ が存在するって先祖に $ U_i $ がいる、つまり $ U_i $ の部分木内ということをややこしく言っているだけだな。根への最短パスの長さが $ D_i $ と言うのも単純に深さが $ D_i $ ということである。まとめると $ U_i $ の部分木内に深さ $ D_i $ の頂点はいくつ存在するかと言う問題になり、Euler Tour と Wavelet Matrix の rank 関数で問題なく解ける。Wavelet Matrix を貼るのをやめて、vector を $ N $ 本持とうか悩んでいた時間が世界で一番無駄だった。後で Euler Tour + vector $ N $ 本をライブラリなしで書きなおしたところ普通にテキパキ書けたので、アホくさとなった。

F問題。最悪。凸包を構築しながら DP をして三角形の符号付面積の和のパリティが $ 0 $ のやつ数え上げていくのだと思った。脳が混乱して時間内に合わせることは不可能となった。こういう問題を時間内に合わせられるようになりたいな。

E までを早く解いていれば黄色になることができただろうが出来なかったため 1975 になった。ジワリジワリと近づいているが、こういうときの一回の事故はメンタルを崩壊させるためつらい。ARC 頼む。

コンテスト後 F 問題を書き続けているがサンプルすら合わない。人生が終了した。そうこうしているうちに TCO Round 2A の時間となった。

Easy。問題文が脅威的に長いし、明らかに不必要な部分が多い。open then rated でコレをやるの悪質な嫌がらせではないだろうか。最悪な気分になりながらも仕組み自体はそこそこ面白かった。証明されているけど一般に非自明に感じてしまうマジックって結構あるし、問題にできそう。

Med。大嘘を展開しており、記録するのも憚られるためノーコメントで。

うーん正直このコンテストでなくてよかったな。寝る。

05/23 (SUN)

12:00 起床。マジで起きられない病気になってしまっている。今日は活動をする。 人々がいてピアノができる雰囲気ではなかったのでパソコンでやるべきことを処理しようと思う。 始めたぐらいの時間に昼食の時間になってしまう。

昼食は確か昨日の残り物+α だったと思う。実家ぐらしなので出てくるのが有難い。喜んで残飯処理係になりまつ。 作業に戻る。しばらく作業をして、まあ日曜だしこのぐらいでいいかと言う気分になる。

競技プログラミングをすることにした。昨日の F を書いてみる。やはりサンプルすら合わない。一体どうしてだろう…これ故に赤 Diff なのだろうということを再確認しつつ、日を改めることにした。 そういえば昨日はボーっとしていて典型を見ていないことに気が付く。

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

RGB からなる長さ $ N $ の文字列 $ S,T $ が与えられる。$ N \times N $ の表に $ S_i = T_j $ なら $ S_i $ を、そうでないなら $ S_i $ でも $ T_i $ でもない色でマス $ (i,j) $ を埋める。$ i-j = k $ のとなるような $ (i,j) $ が全て同じ色で塗られているような $ k $ を数え上げろ、と言う問題。

こういうのはとりあえず $ 0,1,2 $ に置き換えるところから始める。が、そんなにいい性質が見えてこない。$ S $ に対する $ T $ の位置が $ k $ に対応して、重なっている部分を見て色を塗るように考えられる。色 $ c $ で塗られるには $ c $ 同士か $ c $ 以外の二つの組しかないな~う~ん、なんとなく文字列アルゴリズムぽいなでもわからん~。みたいなことを一時間ぐらい考えてしまった。久々にわからない問題が来たのでワクワクしながら解説を読むことにした。

色 $ c $ に塗るためには $ c $ 以外の色が $ S $ に出現した際には、さらにもう一つ $ c $ でない色である必要がある。重なっている部分の文字の対応関係を 色→色 の写像として考えたときに全単射なので、$ S $ か $ T $ において $ c $ でない色同士を入れ替えてやれば、普通の文字列のマッチング問題として解ける。ちなみに全単射は必要条件ではなく、対応関係を二部グラフで考えたときに出次数が高々 $ 1 $ になっている方の文字列を書き換えることでマッチング問題に落ちると思う。

$ 3 $ 種類に文字列 $ T $ を変換することで文字列マッチング問題に落ちた。しかし、まだ問題は解決していなくて単純にマッチングすることを考えると効率のいいアルゴリズムでもマッチング文字列の長さの合計ぐらいの計算量がかかり今回は $ O(|T|^{2}) $ で明らかに間に合わない。よく考えるとマッチング文字列は $ S $ と $ T $ の prefix と suffix(逆も)が対応しているため、Z-Algorithm を使えば効率よくマッチングできる。解説にはローリングハッシュが書いてあったが怖いのでこちらかな?

この問題からは結構知見が得られて満足した。 色々しているうちに ARC の時間になる。

AtCoder Regular Contest 120 - AtCoder

A 問題。普通に難しい。困るも、最大値を足したら確実に最大値になるやつだということに気づいたら prefix max の寄与が $ k $ 回、それぞれの要素の寄与が等差数列になっているため累積和の累積和を前計算することで AC。

B 問題。これも難しい。作るグリッドは対称であることは間違いないな~と思って眺めていたら、$ i+j $ が等しいマスを全て同じ色にしなければならないことに気が付く。あとはちょっと場合分けして AC。

C 問題。難しい。位置と数字が大事だと気づく。目標の数字を目標の位置に入れるには 数字+位置 が同じでなければならないと気づきを得る。数字+位置 のヒストグラムが等しければあとは転倒数でできるが、重複ありで座圧と数字の変換が必要な転倒数の実装に不慣れで $ 30 $ 分近くかけた。反省。

D 問題。大きい数字から $ N $ 個をプラスに寄与させることができそうなことに気づく。しかし、何を思ったか偶奇で分けて昇順降順で対応させれば構築できると思ってしまった。これは意図通りに対応しない可能性があるだろ…コンテスト後に過ちに気づき、プラスに寄与させる数字に mark を付けて stack を用いて mark を付けているのとつけていないのを対応づけて AC。

EF は読んでいない。

明らかに本番の動きをしくじって 1955(-20) になってしまった。来週こそ黄色になる… 睡眠習慣が頭おかしいことになっているので今日こそぐっすり寝ることにした。レベルの高い睡眠をとるんだ…。

そんなで今週はうまく活動と競技プログラミングができなかった週だったように思える。 来週はもうちょっと睡眠をうまくなって活動をしようと思う。 あと来週はちゃんと昼食の写真を撮る。

P.S. ここまで書いて、金曜に書いた最小費用流の verify をしていないことに気が付いた。すみません…

週記(2021/05/10-2021/05/16)

05/10 (MON)

9:00 前後に起床。月曜は研究室に行って on demand な講義を再生したり作業をしたりする日にしているが、今日は大学に提出書類などを作成するなどしていてゆっくりめに家を出た。この時間の電車は空いていて最高だと思う。 行きの電車の中で今日の典型 90 問を見た。

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

二次元平面上の点が $ N $ 個与えられて、指定された $ Q $ 個の点について、$ N $ 点の中で最遠のマンハッタン距離を答えろというもの。これどうせキーワードは「マンハッタン距離は 45 度回転」だろ。

まあ「45 度回転」なんて思わなくても $ |X|=\max(X,-X) $ であることを思い出せば、すぐに $ 4 $ 通りの式の $ \max $ であることに気づき、変数分離をすることでそのうち本質的なものは $ 2 $ つであり、マンハッタン距離は $ (x+y, x-y) $ のチェビシェフ距離と等しい結果が得られる。比が違ったり次元多かったりしたときにも使えるテクニックの方で頭に入れておきたいと思って再確認した。 この時点では眠くてスマホコーディングする元気はないので帰宅したら書こうと思った。

f:id:spider_0859:20210511004151p:plain:w300

このタイミングで毎日の生活にメリハリがなさすぎるため、週記を付けることを決意。

昼前に大学に到着する。昼前なのであまり作業もしないまま大学に来ているキッチンカーへ先輩方と向かう。曜日によって来るキッチンカーが決まっているが、月曜はケイジャンビーフチーズ&ライスを毎週食べている。牛肉とチーズが好きなチー牛野郎なのでこれしか食えない体にされつつある。 飯のあと、ゼミがある。後輩の輪講 ONLY の回だ。去年僕も読んだコードなのだがあまり詳しく思い出せないな、などと思っているうちに終了。昼からは作業をしていた。具体的には書かないが、C++ のコードを C で書きなおす必要があり本当に助けてほしかった。

20:30 頃に大学を出た。さすがにこの時間から飯も食わずにゲーセン行くのは戦士すぎるため直帰。帰りの電車では普通に寝まくっていた。デレステの営業だけ設定したかも。

帰宅。実家住みに感謝しながら晩御飯を食べる。おいしい。 今日の典型をコーディングする。脳が解けていてなぜか 2WA 貰いながら AC。 学部生の課題の採点、仕事、ピアノの譜読みなど色々なことに思いを馳せながら全て投げて ARC 118D - Hamiltonian Cycle の続きを考えていたが、解けない。 競プロすら投げて、今日は今朝買ったジャンプを読む。2:00 頃までじっくり読んでいた。 Dr. STONE の続きが最近とても気になる。まだスイカ以外のキャラクターは石化したままだ。 矢吹健太朗の絵が結構好きなのであやかしトライアングル読んでいるのだが、読んでる最中に親が入ってきたら嫌だな。今週もエッチだったし。 というかジャンプに掲載されている殆ど全ての作品は読んでいる。少年なので。 気が付いたら寝ていた。

05/11 (TUE)

13:30 に起床。最悪。驚くべきことにこの時間で二度寝はしていない。一度寝でここまで寝られる日はなかなかない。スマホで時間の確認と今日の典型の確認をする。

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

$ N $ 個の料理が与えられて、それぞれが $ L_i $ 以上 $ R_i $ 以下のコストをかけて $ v_i $ のスコアを得る。コスト合計がちょうど $ W $ になるような料理の作り方があれば価値の最大値を答えよ、という問題だった。制約を見て O(NW) とか O(NW log W) が間に合うのでナップザック DP である。連続部分列に対して同じ更新を行う DP は遷移をセグ木を使って高速化できる。この場合は in-place DP でセグ木高速化をするのが一番楽そう。一回の更新の中で幅が一定なので、スライド最大値を使って余計な $ log $ を付けずに済んだりする。ABC200E - Patisserie ABC 2 もこれだった(こちらは更新が加算なのでより簡単に $ log $ が取れるが)。さすがに典型☆5は見た瞬間だな。

朝食が消滅したので、親に申し訳なく思いながら昼食をとる。本当にカスなので申し訳なさがすごい。今日は講義を受ける予定もなければ、コンテストもないし大学へ行く予定もない。明日の昼までのショートレポートがあるぐらいだと思う。このショートレポートは講義内容の要旨と軽い意見を 400 字以内にまとめるというもので、講義を受けてさえいれば一瞬で終わる。などと思いながら午後の過ごし方(すでに午後だが)に思いを馳せていた。

飯を食べ終わったので、採点、仕事、ピアノの譜読み、作業の 4 つの内どれをやろうか悩んだ。正直どれもクソ大事なタスクである。ピアノのレッスンが明日なので、とりあえず譜読みを優先することにした。Twitter で競技と音ゲー以外のことを全く話さないため自分がピアノを弾かなければならないことを時々忘れる。実家住みでピアノがあることはすごく有難いが、家族の都合に合わせて練習をしなければならないのは、このコ某ナ禍の苦しみポイントの一つだと思う。

16:00 ぐらいからウォーミングアップから譜読みを開始。ラ・カンパネラと言う曲なのだが、譜読み自体は簡単で手の運動が鬼のように遠い。アマゾンで第三の腕を購入したいレベルで遠い。体感 5 キロぐらいある。四苦八苦しながら 3 時間ほど練習した。早くある程度弾けるようにならなければ…

夕食をとった後、今日の典型を実装する。in-place DP をセグ木で高速化やっぱり実装が楽だ。in-place だとキャッシュに載りやすくなり思っているより早くなるからあまり $ log $ を落とす気にならないんだよな。とはいえいざと言うときに落とせないのはまずいと思ったのでスライド最大値でも通しておいた。deque に添え字を入れる実装をしているのに添え字と比較していたりして無駄な時間を要した。 スライド最大値(最小値)はほぼ自動で書けるようにしておきたいな。

この時点でもう今日は休むフェーズに入ろうと思ったのだが、ここで昼食時に思いを馳せていたところの 400 字レポートを書くことにした。講義音声が配られるタイプの講義なのだが、3 つある内の 3 つ目の音声が壊れていることを思い出した。報告しようとしていて完全に忘れていたのだが、課題に関係ある部分でなかったため 400 字のレポートを書く。せっかくこの時間に身体を縦にしていた記念として、ついでに on demand の講義を一つ消化しておいた。大体知っている内容で涙がちょちょ切れてしまったが消化したという精神的優位が得られたため良しとした。

提出を終えた後は、競技プログラミングを少しやった。虚無を 2~3 問と青 diff を 2~3 問解いた。 経験的に二分探索をしたくなるような設定でなぜ二分探索が効くのかについてちょっと整理したくなってきた。いろんなパターンがあるため、これから見つけたらメモしておこう…

布団に入ってもこうの動画をみているうちに寝落ちした。

05/12 (WED)

11:00 に起床。二日連続で寝坊したが、このぐらいならまだ許容範囲かな。トーストとコンビーフの朝食をとる。例によって今日の典型を見る。今日は☆3 か。

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

$ 2 $つの整数 $ A,\,B $ が与えられてその最小公倍数を求めよ。ただし $ 10^{18} $ を超える場合はそれを報告せよ。と言う問題だった。 最小公倍数は $ \frac{A \times B}{\gcd(A,B)} $ なので $ \frac{A}{\gcd(A,B)} $ と $ B $ の掛け算が $ 10^{18} $ を超えるか確認すれば良い。単純にやるとオーバーフローして壊れるので $ \frac{A}{\gcd(A,B)} > \left \lfloor \frac{10^{18}}{B} \right \rfloor $ で判別すればいい。多倍長や 128 ビット整数を使えばそのままいけそう。

余談だがこの記事を書いている最中にまた床関数とかの括弧の大きさを自動で調整するやつの書き方を調べた。全く覚える気がないので本当に毎度調べてしまう。よくまとまっているチートシートをローカルに落としてしまおうか…

そうこうしているうちに正午を回ってしまう。譜読みの優先度が MAX なので昨日の続きをすることに。 昼飯には、買ってきてもらった弁当を食す。そぼろと卵の弁当なんだけどシンプルでおいしかった。食した後また譜読みに戻る。 右手が言うことを聞かないため叱咤していたら時間になってしまっていた。急いで家を出てピアノ教室に向かう。下手すぎて泣きそうになるも、終えて帰ってくる。

ピアノから帰ると 15:30 ぐらいで典型のジャッジが来ているかなと思って確認したら、追加されていたので提出。AC。 今日は作業をしなきゃいけないんですよね~って心のクソデカ声で叫びながらちょっと疲れたのでデレステを起動した。

馬鹿なので 3 時間ぐらいデレステをしていた。理性の敗北。でもデレステの感覚を思い出してきた。そうだこのゲームをスマートフォンでやるにはそれなりにコツがいるんだった。具体的には複数指運指の使いどころが難しい。

f:id:spider_0859:20210512222016p:plain:w300
Radio Happy [MAS+] をとりあえず FC 。AP でないので不満。

f:id:spider_0859:20210512222105p:plain:w300
段々解ってきた Gossip Club [MAS+]。近日中に AP したい。

夕食を食べたらさらにやる気を失ってしまった。2 時間ぐらいマンガアプリでマンガを読んでいた。5 時間連続で生産性のない活動をしていたことになるのでまずいと思い、せめて競プロをすることにした。とくにやりたい問題もなかったので Problems の Recommend 機能を使うことにした。D - Double Landscape があったので適当に選ぶ。Diff 1670 だと思って舐めていたら酷い目に遭った。普通に 40 分以上かかったので割と助けてほしいな。

問題概要は、$ N \times M $ の表に対して $ [1,N \times M] $ の数字を重複なく書き込むことを考える。$ A_1, A_2, \cdots, A_N $ と $ B_1, B_2, \cdots, B_M $ が与えられて、$ i $ 行目の最大値が $ A_i $ 、$ j $ 列目の最大値が $ B_j $ となるような書き込み方の通り数を求めよ、というもの。重複がないから $ A $ や $ B $ の内部で数字の重複があったらその時点で $ 0 $ なことがわかる。また、$ A $ にも $ B $ にも含まれる数字がある場合、その行と列が交わるマスは必ずその数字を書き込まなければならない。また、とりあえずマス $ (i,j) $ は $ \min(A_i, B_j) $ 以下の数字を書き込まなければならなそうだということがわかる。大きい数字の方が明らかに書き込みづらいので、制約を守るようなまだ書き込まれていない $ X $ の書き込み方を $ X $ の大きい方から求めて掛け算をしていくといいと思った。最後のサンプルが合わない。参った。よく考えたら、$ A $ や $ B $ に数字があるってことは、その行や列にその数字がなければならないことに気が付いた。行や列に書き込みのある数字の場合はより強い制約で置くように書きなおしたらサンプルが合う。提出。AC。 こういう問題を速く解くにはどうすればいいか途方に暮れていた。と思ったけど自分で最初に書いていた条件を忘れていただけなので競技痴呆をやめることによって改善されそう。自分で書いた考察メモはちゃんと見よう!

C - 掛け算 も Recommend されていたためやる。$ a_1, a_2, \cdots, a_N $ と正整数 $ A, B $ が与えられるから、数列で最小の数に $ A $ を掛けるという操作を $ B $ 回行った結果をソートした上で、$ mod 10^{9}+7 $ で答えろという問題。冷静に考えると、 $ a $ 内の数字は実行する演算に比べて差が小さいなと思う。全部が $ 1 $ 回以上掛けられたらすべての数を $ A $ で割ることで過去の状態と同一視することができる。全部が $ 1 $ 回以上掛けられるのにかかる操作回数は $ A \geq 2 $ なら $ O(N log A) $ ぐらいな気がする。これぐらいなら愚直に計算が余裕にできる。結構実装が嫌で、疲れていることもありいやいや言っている時間が長かったので反省。結局 $ A=1 $ のパターンを忘却して $ TLE $ を一回食らってしまった。

この時点で 1:00 になっている。木曜は早起きしなくてはならないため寝る。

05/13 (THU)

7:00 起床。眠いし寒い。適当にパンを食して家を出る。家を出て少し歩くと雨が降っていることに気が付く。最悪だが予定した時刻の電車に乗れないのはもっと不愉快なので我慢してそのまま行く。 いつもの通り電車内で今日の典型を確認する。

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

問題概要は、$ N $ 頂点の木が与えられてすべての頂点の組に対してその距離の和を求めよ、というもの。脳がうまく起動していないのか最初に全方位木 DP をして最後に $ 2 $ で割る解法を思いつく。もちろんこれでも $ O(N) $ なので問題はないが、こういう問題は寄与を考える方が筋が良いだろう。実際にそれぞれの辺の寄与を考えると、その辺を切ったときに出来る $ 2 $ つの木のサイズの積になる。これを足し合わせればいいので部分木のサイズを持つ簡単な木 DP で良い。

大学に着く。木曜日はオンラインの 1 限があるのだが、これを受けてから登校すると微妙な時間なのでいつも大学で聴いている。今週の課題はものすごく簡単そうということがわかった。今日は朝から胃が重くダルかったのであまり作業に身が入らない。だめそうなので研究室に置いてあるルービックキューブで遊ぶことにした。過去のしょっぱいタイムを塗り替えるために普段使っているのとは別の揃え方を調べて覚えた。作業に戻ったり、周りの人と喋ったりしているうちに昼の時間となった。

木曜はキッチンカーのタンドリーチキン丼をたべることが決まっている。いい加減別のメニューを試したいが冒険して口に合わなかった時のことを考えるとできない。胃が重いためタンドリーチキン丼が想像よりつらかったけどいつも通り美味しかった。

色々やってちょっと早めに大学を出た気がする。大学を出る前に典型を通す。作業はできたと思ってから何度もデバッグをしていたし、体調も微妙だったので今日の進捗はあまりよくなかった。気分転換にゲーセンに行くことにした。身体が不調なのか指が思い通りに動かなくて困った。一応それなりに満足して帰宅。

帰って夕食を食べる。帰ったら夕食があるって本当にありがたいことですね…。今日は何をやってもダメそうなのでベッドで横になった。 週記の今日の分を書いていないことを思い出したので急いで書く。日付も回っているので今日はもう寝ようかなと思うが典型以外一問も通していないのはマズそうなので少しだけ競プロをやることにした。

B - Boxes を解くことにした。 問題概要は、円環上に数字が並べてあって $ 1 $ 回の操作で任意の位置から時計回りに $ -1, -2, \cdots, -N $ を数字に実行できる。この操作を任意回行って全ての数字をピッタリ $ 0 $ にすることができるか判定せよ、というもの。問題がシンプルでかなり好み。問題文のみからでは自明な解法は浮かばない。引いていくこと考えるのは面倒なので、逆の操作で最初の数列を $ 0 $ から構成できるかを考えた。自明な性質として、$ 1 $ 回の操作で総和は $ \frac{N(N+1)}{2} $ 増える。よって与えられた数列の総和がこの倍数でなければ NO が判明する。ちょっと詰まるも $ 1 $ 回の操作の右隣との寄与の差は大体 $ +1 $ で端と端の部分だけ $ -(N-1) $ である。差に注目すればもっと扱いやすい制約として考えられそうだ。操作回数は 総和÷$ \frac{N(N+1)}{2} $ で決定するため、それぞれの位置について連立方程式から操作の開始位置として選んだ回数を求められる。あとは非負整数条件や操作回数の条件を確かめて問題がなければ YES。AC。考察 $ 15 $ 分の実装 $ 5 $ 分。難しい実装でもないのに遅い気もする。

うーん、操作が厄介なため操作が単純になるような量に着目するのは典型な気がする。あとは未知数が $ 2 $ つの式が一つしかないからもう一つを探すというのもアプローチの一つかもしれない。

あと気分でCoding Gameを登録した。やり方は明日にでも見ようか。

05/14 (FRI)

9:00 に起床するも、昨日のダルさが全然抜けてなかったので二度寝して正午過ぎに起床。朝食は食べないことにした。 レトルトのハヤシを温めている間に今日の典型問題を確認する。今日の問題は☆7なので見てすぐとはいかない。ハヤシを食べながら典型問題を考える。食べながらだと余り集中できないが、問題をグッと睨むと $ O(N3) $ で解けた。と思ったが嘘だった。わざわざ嘘のためにスペースを使うのはもったいないので割愛。改めて考えると依存関係にサイクルがないため、最小カットで最適化できるタイプの問題であることがわかる。世間では「燃やす埋める」と言われるやつだろう。実はまだ最大流ライブラリを作っていないため、WSL 環境でこの問題を通すのが面倒なので、実装を後回しにする。ライブラリをちゃんと作って早く人間になりたい。

典型を考えたり Twitter を見たりしている内に TA の時間がきた。TA の時間、最近本当に暇なため手元でずっと作業をしている。三週連続ぐらいで一回も質問が来ない。学部生の間で使えない TA の烙印を押されている可能性があるな。最後にされた質問も Eclipse の使い方だし、本音ではそんなの俺に聞かないで欲しい。TA の時間が終わると、ゼミの時間となる。自分の発表回ではないため聞く。色々あったが終わる。やんわりゼミの後に教授と相談する予定になっていたのだが、それを zoom で言い忘れる。これ確か前もやった、人はなぜ同じ過ちを犯すのか。急いで slack で連絡したら相談に漕ぎつけた。懸案事項も解決してハッピー。

夕食を食べる。夕食後はダラダラしていた。具体的には YouTube を閲覧していた。もこうがマナー講師にバチボコに怒られている動画面白すぎて呼吸困難になる。

例によってこのまま日付が変わるのはよくないと思い AtCoder Problems を開く。

D - Classified を解くことにした。こういう問題結構すき。問題概要は、$ N $ 頂点の完全グラフがある。全ての辺を正整数で色分けして、同じ色の辺を使って移動して元の頂点に戻った時に通る辺の本数が偶数になるような色分けで辺に割り当てた最大の整数を最小化せよ、というもの。

一番最初に出来るだけ少ない二部グラフに分解する問題だなぁということを理解した。最初の $ 10 $ 分ぐらいは $ N=4,5 $ の図を書いて唸っていた。とりあえず、頂点数 $ N $ の二部グラフを考えてみたところ、よく見たら補グラフは完全グラフ 2 つになっていることに気づいた。完全グラフのサイズが小さい程最適なのは自明なので、できるだけ半分に分割すればいいわけだ。分割統治的に再帰的に解けるなと気づいたので実装に入る。実装が下手でビビった。あと偶奇で分割していたが余計混乱する原因になったので反省。$ 15 $ 分ぐらいかけながら AC。 思ったけどこういう問題、大体再帰的に解けるよな。メタ読み下手くそなのであまり意識しないようにしてはいるけど。

C - 収集王 も解いた。グリッドに $ N $ 個のコインがあってあるマスに降り立つと同じ行/列のコインを収集できて、ちょうど $ K $ 枚収集できるような降り立ち方は何通りかと言う問題。これは流石に自分にとってはやるだけにしないとまずそう。グリッドがデカく $ N $ もデカいので二次元累積和とかはできない。同じ行/列の個数系の問題は交差する地点に置いてあるかどうかだけが本質がち。行/列についてそれぞれ何個コインが存在するか求めておいて、和が $ K $ になるものを基本的に考えればいい。降り立つ地点(=交差する地点)にコインがあって和が $ K $ の数を引き、$ K+1 $ の数を足すことで問題ない。AC。$ 10 $ 分以内に AC できなかったので反省。

05/15 (SAT)

11:11 起床。朝飯を食しながら今日の典型を確認する。

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

$ N $ 個の座標が与えられて、それらを全て含むような最小の周を持つ多角形で覆う。この多角形の中にある (周も含む) 格子点の数を数えよ。 多角形は明らかに凸包。なので $ O(N \log N) $ で凸包を作る。最初に思いついた解法はそこから三角形に分割して Floor Sum を使って内部の格子点の数を重複を気にしながら数え上げるというものだったため、いやだなぁという旨のツイートをした。 しかし冷静になると、ピックの定理 - Wikipediaとかいうのがあったなあと思い出す。多角形の面積は原点中心の三角形の符号付面積の総和で求められる。辺上の格子点の数はまあ頑張って数えれば、あとは定理の式を整理すれば答えが出そう。

典型を考えていたり、ちょっとだけ作業をしていたりしたりしたら昼食の時間になってしまう。

昼飯を食いに出かける。ファーストキッチンを食べた。ここのポテトの質めちゃくちゃ高くないですか?すいてる昼飯どころ目的で来たけどポテトがうまいのを思い出せて満足。そのあとはゲーセンに向かう。身体の調子は悪くなさそうなのだが、あと一歩みたいなのが多かった。もうそういう日だということにした。最後の悪あがきをしたら SOUND VOLTEX で初の 19PUC が出た。一応めでたい。欲を言えばもっとかっこいい曲で決めたくはあったけど。

f:id:spider_0859:20210515191718j:plain:w300
音楽 -resolve- [VVD] PUC

帰宅。鬼のように音ゲーをしていたせいで帰ると 19:00 前とかそんなん。 晩飯を食べる。音ゲーで完全に疲れているけど今日の ABC 大丈夫かななどと思う。とりあえず指のウォーミングアップも兼ねて既 AC の問題を解きなおしたりして時間を待つ。ABC が始まる直前に口にガムを放り込み集中力を高めようとしてみる。 A-E が「実家」みたいな問題だったため、ガムの集中力もあってか自分にしてはそう悪くないタイムで駆け抜けられる。 F がクリティカルっぽい考察までいくも詰め切れずタイムアップ。132 位で perf 2400 なのでヨシ!レートが 1964 になった。東京五輪だ。 しかし明日は ARC だ…流石にここまできて 1900 付近に戻されたら萎えるので体調によっては不参加を決めさせていただくかもしれない。

さて、 Google Code Jam Round 2 がある。ABC が終わって間もなく始まるのでバタバタしたが、特に問題はないように思える。特別眠くもなかった。

A 問題を開く。いきなり interactive である。interactive は詰まると絶望しかないので、戦々恐々としながら問題文を見る。見えない数列があって、区間を与えると最小値のインデックスが返る query をコスト $ \frac{10^{8}}{r-l+1} $ で実行できる。 $ 6 \times 10^{8} $ までコストを消費できて、こいつらをスワップすることで昇順にしろ、と言う問題。見た瞬間調和級数かな?と思ったが、そんな簡単なわけが…と謎読みをしてしまい時間を浪費する。全人類が一瞬で通しているため投げると通る。

B 問題を開く。問題については長くなりそうなので割愛。コイツに自分の今回の GCJ は破壊されてしまった。コーナーケースを見落としたり、コーナーの処理をミスったりして 4~5 ペナと無限時間を費やして AC。

C 問題を開く。こちらも問題については割愛。個人的にそんな得意そうな問題ではないし、small を通そうと思ったが順位表を見るにこれは large も通さないと結構やばそうな雰囲気があり、しばらく考えた後一旦 D 問題に行くことを選択。

D 問題を開く。難しそう。問題文は割愛するが、small は二部マッチングを解けばよく、Dinic を貼って通す。が、実装がへたくそすぎて、かなりの時間を費やしてしまっていた。

C に戻る。しばらくサンプルを使って色々試したり、唸ったりした結果 large まで解けた。が、この時点で残り 2 分だった。もう small すら間に合わないなと思ったので日本人の順位表を眺めたりしていた。

最終順位は 1514 位、c を投げていたら順位はもう少し上がっていただろうが読み通り ABcd は落ちていたらしいのでやはり C を通さなければならなかったな。A の迷いの時間、 B と d に使った時間みたいなのを何とかすれば来年は Round 3 に進めそうだな…

完全にふてくされてしまったので、明日は何もしないことにした。寝る。

05/16 (SUN)

12:00 起床。よく寝た。朝ごはんは食べないことにした。最近朝食を抜きすぎているのでそろそろ反省の方をさせていただきたいと思います。兄と一緒に KFC を食べに行くことにした。食べた。おいしかった。KFC のオリジナルチキンっておいしすぎないか?ウマ娘の話とか聞きながらダラダラして、ちょっとゲーセンで遊ぶことになった。

f:id:spider_0859:20210516165018j:plain:w300
VALKYRIE ASSAULT は PUC を狙えるかもしれない

うっかり DDR にクレジットを入れてしまったため全身疲れているが、17:00 からえでゅほがあるため帰宅。

https://codeforces.com/contest/1525

A 問題。$ 1 $ リットルずつ入れて行って $ k : 100-k $ を作る問題。最大公約数でしょう。

B 問題。全体以外の区間を自由に並び替えられる操作を何回で与えられた数列を昇順にできるでしょうという問題。 昇順なら $ 0 $。端が正しい数字なら $ 1 $。それ以外なら $ 2 $。とやってしまいがちだが、よく考えると左端に $ N $ 右端に $ 1 $ がある場合は $ 3 $ になる。 結構ペナをもらっている人が多かった印象。

C 問題難しくて、D 問題を先にやる。一列に並んだ空き席と座られている席(半分以下)があって、人を移動して元々座っていない席にのみ人を座らせたい。移動量の最小値を求めよという問題。 これは移動先の空き席の集合が決まれば左から順番に人を割り当てれば良い。移動がクロスしなければ損しないよくある奴だ。この前のえびまさんのお誕生日コンテストでも見たな。E - Min Cost Sort ←これだ。 よってあとは空白を使う使わないを選択していく二次元 DP でいける。

C 問題。難しい。左右どちらかの向きを向いているロボットが一次元上に配置されていて、$ 1 $ 秒に $ 1 $ 向いている向きに移動する。左右に壁があり、壁にぶつかると向きを変える。ロボットどうしが整数座標でぶつかると爆発する。それぞれのロボットが爆発する時刻を報告せよ、という問題。 パリティが一致するロボットしかぶつかって爆発しないので分ける。あとは set をそれぞれ $ 2 $ つずつ使って時系列に沿ってシミュレーションする。こういう set いじいじ系が本当に苦手。

E 問題。制約で罠を仕掛けに来ている。$ N $ 個の直接支配する都市と、支配したい $ M $ 個の地点が与えられる。それぞれの都市から $ M $ 地点に対する距離が与えられて、支配されたターン数で支配領域が $ 1 $ ずつ増えていくので、ランダムな順番で $ N $ 都市を支配した時の支配できる地点の個数の期待値を求めよ、という問題。 最初はゴニョゴニョ bit DP とか考えていたが、期待値なので主客転倒を考えると、余事象が簡単に求められるため答えが出る。C より簡単じゃないか?

残念ながら E のバグとりが間に合わず 4 完。まあ耐え。

夕ご飯をたべる。肉がうまかった、助かります。 お腹いっぱいで ARC を辞退しようかかなり迷ったが、まあなんとかなるの精神で出場。

AtCoder Regular Contest 119 - AtCoder

A 問題。こういうのは一番影響のでかい文字から決め打っていく。今回は $ b $ を決め打てばあとは $ a $ を最大化するだけ。

B 問題。クロスせずに $ 0 $ を移動するだけ。さっきの問題の残像で解けるな。

C 問題。むずい。足してから引けばいいので実質マイナスは気にしなくて良い。区間に着目した時に端から消していって全部消せたら OK なのだが、その手続きを式に落とすと引き算の連結になり偶数和と奇数和が一致することと等価であることに千年かけて気付く。遅すぎる。偶奇の寄与を +- として累積和テーブルを作っていつもの等しい組みを数えるやつ。

D 問題。むずすぎ。依存関係をグラフにして SCC をするという嘘を生やす。これを一時間以上かけて実装して丁寧に WA をもらう。これで最大化できるのは操作列の最長だ・・・

E 問題。リバースというが、評価値が影響を受ける範囲はスワップより少ない。隣接二項を方向つき区間としてやると、これをつなぎ変えることになる。よく考えると逆向きの区間どうしをつなぎ変えても意味がないことに気がつき、最終的に区間の共通部分の長さの倍だけ改善することがわかり、あとはイベントソートなりなんなりで解ける。この問題を先にやってればなあ・・・

C が遅かった割には 耐えていた。ナイス耐え。黄色入りは来週以降に持ち越し。

なんかすごい夜更かしをした気がするが、何時に寝たか覚えていない。

週の後半はなんか自由人みたいな生活を行なっていたが、週記を始めたことで横になっている時間は減ったのでこの調子で来週も活動をしたい。