/ 最近 .rdf 追記 設定 本棚

脳log[2025-12-06~]



2025年12月06日 (土) [AtCoder] 今日は AtCoder Beginner Contest 435 があった。終了1分前にバグの原因に気がついて修正して提出してコンテスト終了後にまだジャッジが進んでいるのをドキドキで見つめていた。それが E 問題。今日は F 問題までそれなりの早さで解かないといけないセットだったらしいです。■A 問題「Triangular Number」。三角数? N*(N+1)/2 ■B 問題 No-Divisible Range。愚直に、やります。■C 問題 Domino。どこまで倒せるかをメモしながら左から倒していく。違った。どこから倒せないかをメモしながら左から倒していく。■D 問題 Reachability Query 2。黒いマスを始点にして逆向きに辺をたどって通り道の頂点も黒く塗っておく。どの頂点も高々1度しか塗られないし、塗られたときにしか遷移しないので、全体で N+M に比例した処理。クエリ1で与えられる頂点がすでに黒いかどうかを確かめずに無条件に探索を開始したら TLE×2 を食らった。テストケースがいい仕事をしている。多くの辺を集めている頂点が何度も始点になったら、たとえその次の頂点が黒で探索がストップするとしても、最初の1ステップが O(M) で死ぬ。■E 問題 Cover query。区間の併合。BIT で区間の始点を管理した。座圧が必要。とてもやっかい。時間をかけて丁寧に書き何度も読み返し2歩進んで1歩戻る慎重さ……というか自分が今何をしているかを思い出す時間を確保しながら書いていた。とてもやっかい。最後まで見つからなかったバグとは何か。BIT で管理している区間の始点の集合が壊れている。単調増加のはずなのに途中で減少したりしていて、それでは BIT 上の二分探索ができない。なぜ壊れたか。ある位置を含みうる区間(始点がある位置以下にある直近の区間)を BIT から検索していたのだけど、ある区間の始点を基準にして、その位置を含みうる直前の区間の始点を検索していた。何が見つかるかは火を見るより明らかなんだけど、座圧をしているとデバッグプリントの解読が難しくて思い違いになかなか気づけない。十分に早い SortedSet があれば座圧は必要ないのになあ。遅延セグメント木を使う解法と、BIT を使っていながらもっとシンプルな解法があるみたいなのと、自分と同じような解法ながらずっと早く提出している人がいた。要するに、考えが足りず、実装も下手だった。これが現在の自分。■F 問題 Cat exercise。実装前にいろいろ考えた。移動を開始すると移動可能な範囲は必ず左右に2分割される。左右のどちらに移動させるかは選べる。移動先の高さを選ぶ意味はあるだろうか。……ない。じゃあ左右の移動先を効率良く見つけるためにセグメント木と値から添字の逆引きインデックスを用意すれば終わり。E 問題より簡単。「……ない」の点々部分について書く。移動先を選ぶということは、(1)優先される移動先を予め取り除いておく、(2)移動範囲を予め制限しておく、のどちらかを実行することになるのだけど、(1)をするくらいなら優先される高いタワーに寄り道をする方が移動距離が増える。(2)を実行するのは今ではなく制限のために取り除くタワーの隣に移動してきたときでいいし(つまりこれが左右の移動先を選ぶというときの実際の操作)、そのときを待つ方が移動距離が伸びる。■■■F 問題。O(N) で解けると読んだので考えてみた。頭の体操。こういうときに使えるデータの持ち方を知っている。AtCoder を始めたごく初期の日記に書いてある(脳log[20190907p01] AtCoder Beginner Contest 140 E問題)。結局、左右にある直近の現在より低いタワーの位置が定数時間でわかればいいのだ。高さ N から降順でやるのに失敗したので逆に、高さ1から昇順でやることにした。左右にあって最も近くの現在より高いタワー(左右1つずつ)に情報を伝えていく。提出 #71557988 (AC / 165 ms)。


2025年12月03日 (水) 「このテスト関数には問題があります。呼び出しても依然としてエラー終了するおそれが残されており、安全な実行を保証しません」という警告に対して、問題のあるテスト関数によるテストを取り除いて問題を解消していくスタイル。


2025年11月29日 (土) [AtCoder] 今日はSky株式会社プログラミングコンテスト2025(ABC434)があった、と書いている今は日曜日の夜です(日曜日の日記は ARC のために空けておきたい)。D 問題に負けた。茶色からやり直した方がいいよ。■A 問題 Balloon Trip。「AtCoder では秒と分を混ぜたような問題は出さないし、答えに単位も要求しない」と書いたのが先月のこと。単位が出てきました。「単位が kg であることに注意してください」と注意があるなんて学校の問題よりなんと親切なことか。小学生は 1000 を掛けるのか 1000 で割るのか迷うんですよ。でもそれだけ。■B 問題 Bird Watching。数と大きさの和がわかれば平均が計算できる。■C 問題 Flapping Takahashi。高橋君が存在しうる下限と上限を更新しながら判定をする。判定条件に一瞬迷ったけど、下限≦上限で間違いではなかった。いつものように all?any?none? といった Array のメソッドで入力を受け取りながら同時に判定をすると入力を受け取り切らなくて次のケースが狂うことに注意した。■D 問題 Clouds。計算量の見積もりができなかったのが敗因。2000×2000 の二重ループも、全体で N に収まるループも許されているけど、それらが組み合わさって 2000×N のループになっていることに気づけなかった。気がついたらやりようはある。雲のひとつひとつにハッシュ値を割り当てて重なり合いを xor で計算するならグリッドを走査するのに伴う雲の足し引きは定数時間の計算になる。提出 #71342582。どこかのブログを読んだ限りではもっとオーソドックスな解法があるなんてことない D 問題だった雰囲気があるけども、グリッドではなく雲の座標を伝っていくようにすると間に合うんですか?■E 問題 Distribute Bunnies。終了後に読んだけどわからなかった。似た問題が ARC-A あたりにあったのは知っている。たくさんの二択。UnionFind だと見かけたので UnionFind で解いた。でも UnionFind でいけるということが見抜けるようになったことを意味しない。カードに関する問題だったと思ったから AtCoder Problems で問題名を検索したら ARC111-B「Reversible Cards」がそうだった。400 点問題。4年半前の自分の提出 #21761198。ストレートに UnionFind ではないけど UnionFind っぽい処理をしている? 解説によれば連結成分ごとに DFS などで木かどうか判定すれば良いと書いてある。自分の今日の提出 #71357456 が木の判定をしているのかどうか知らないので2つが同じ問題なのかどうかも確かではない。■D 問題。雲が何枚重なっているかをマス目ごとに数えた後で、雲の厚みが1のマスの2次元累積和を作成し、雲ごとに、領域内に厚み1のマス目がいくつあるかを数えるらしい(「ABC434 振り返り - naoya - Obsidian Publish」)。厚み1のマス目の2次元累積和を用意するステップが完全に想定外だった。グリッドを走査するときに同時に1枚だけの雲がどの雲かを特定しようとしていたから TLE になっていた。その段階では枚数だけを数えておけば良かったのだ。2次元累積和を使って A-B-C+D の式で任意の矩形領域の和を得るのなんて簡単だよ。■■■D 問題。雲にハッシュ値を与えて XOR で重ね合わせをしたと書いた。実は最初は足し算と引き算で雲を重ねたり取り除いたりしていて、それでもサンプルが合っていた。なぜ足し算引き算ではなく XOR なのか。たとえば雲をたくさん重ねた状態のビット長がコントロールできないのが不都合なのかと思った。雲のハッシュ値が 40 ビット長だとして 1000 個の雲を足し算で重ねるとざっと 50 ビットがないと状態が保持できない。では雲の最大数が決まっていてビット長が足りているなら足し算で問題ないのだろうか。むしろ状態が 40 ビットを超えると発行済みの雲のハッシュ値(単独)とのかぶりが考えられなくなるのが嬉しいのではないか、と一瞬思ったけど、それなら最初から 50 ビットのハッシュ値を配っておいて XOR で重ね合わせをするのがビットの効率的活用なのかなというところに落ち着いた次第。■D 問題。単に雲の番号を足し合わせたものを状態として持っておけば良い。ハッシュ値はいらない。重なっている層数をあわせて管理しておき、雲が1枚だけのときにだけ雲の番号の和を参照するのだから、雲1+雲2が雲3と判別不可能だろうと関係ない。……ということが復習を終えた段階でもわからないんだなあ。


2025年11月27日 (木) 20251114の続き。パスキー。これまでで一番詳しそうな記事。■「パスキー徹底解説:パスワードレスな未来への完全ガイド - ZDNET Japan」■「第1回:パスキー認証器とは何か?--パスワードレス時代へのカギ - ZDNET Japan」■パスキーという仕組みを成り立たせる独立していたりしていなかったりする4つのアクター(記事ではエンティティとされている)があるという。OS、Web ブラウザ、Web サービスやアプリ(依拠当事者/リライングパーティーと呼ばれている)と最後に認証器(オーセンティケーター)。認証機というのが見えにくい。「パスキーの世界において、オーセンティケーターとは、パスキーの公開鍵と秘密鍵という構成要素を生成・保存し、あらゆる認証セレモニーの際にそれらを取得・使用する技術を指す。Googleのパスワードマネージャーのようにウェブブラウザーに組み込まれているものもあれば、「Bitwarden」「Dashlane」「NordPass」といったサードパーティー製のBYO(Bring Your Own)型パスワードマネージャーも含まれる。また、デバイスのOSと連携したり、Trusted Platform Module(TPM)や「Secure Enclave」などのローカルセキュリティハードウェア、あるいはYubicoの「YubiKey」のような「FIDO2」準拠のローミングオーセンティケーターといった、パスワードマネージャーではないハードウェアとの組み合わせで構成されたりする場合もある。ここで重要なのは、現在のパスワードマネージャーの多くがFIDO2準拠のオーセンティケーターである一方で、全ての認証器がパスワードマネージャーであるとは限らないという点である。例えば、YubiKeyは認証器ではあるが、パスワードマネージャーではない。また、「オーセンティケーター」という言葉の意味は、テクノロジーベンダーやその顧客によって異なる場合があることにも注意が必要だ。」 たとえば Bitwarden がそのひとつだという。Google や Microsoft とどちらがマシかはわからない。どれも選びたくない選ばされたくない雰囲気。


2025年11月25日 (火) 近所のスーパーで一本満足バーの売り場がここ2、3週間欠品のままで、さすがに異常事態なのかなと思ったときにうろ覚えのメーカー名と符合するニュースがあったことに気がついた。システム障害からの正常化がまだみたい?


2025年11月23日 (日) [AtCoder] 昨日は AtCoder Beginner Contest 433 があった。ABCD 4完だけど意外に耐えた。それで耐えられるレベルが情けない話。■A 問題 Happy Birthday! 4。最難関 A 問題来ました。なんもわからん。どっちが大きくてどっちが小さくてどっちがいくつずつ増えてどっちが早く大きくなるのか、なんもわからん。全探索でも許されるのはわかる。でも十分な範囲がなんも見積もれない。実行時間で区切れば 1000 万まではいける。でも 10000 で十分な雰囲気(!)も感じられる。ふわふわといつまでも雲を掴んでもいられないので6分時点でとりあえず投げて運を天に任せた。■B 問題 Nearest Taller。N が 20 万なら考えるけど N が 100 なので考えずに全探索。なんで A 問題がこうじゃないんだ。■C 問題 1122 Substring 2。1 と 2 の境界を全探索して、左右を調べる。高々全長の2倍しか調べないので愚直にやって大丈夫。■D 問題 183183。x と y の mod M が足してゼロか M なら f(x,y) が M の倍数。x の mod M がそのままの値ではない。y の桁数によって 1 から 10 桁まで持ち上げられる。10 から 100 億を x に掛けたものの mod を取る必要があるということ。数列 A の要素ごとに高々 10 通りの mod M なので予め集計しておく。■E 問題 Max Matrix 2。時間を使い過ぎないようにうまく情報を持って順番にマス目を埋めていくだけだと思った。最初の実装を完成させるのに1時間と6分かかった。時間を使い過ぎないようにうまくやれはしたけど、別の意味で時間を使い過ぎているし、WA が出てしまった。提出 #71168194 (WA×4/AC×26)。残り6分なのでランダムケースで考え漏らしやバグを見つけることもできず終了。F 問題は読んでいない。■■■精進。E 問題。WA だった最初の提出 #71168194 に対して必ず Yes となるランダム入力を与えてみたところ問題なく答えが出せていた。だから早期に No と答えている 33 行目が誤っているのかと疑って取り除いてみた。提出 #71212471 (WA×4)。結果に変化なし。では No と答えるべきところで No と答えられていないことが疑われる。ちょっとひらめいて、必ず Yes となるランダムケースの、X 数列の要素のひとつをインクリメントしてみた。つまりある行の本当の最大値よりも1つ大きい値が最大値として指定されているわけで、行列を埋めるに際しては寛容な制約となるが、もちろん制約を満たす最大値を埋めることはできないはずだ(必ずできないかはわからない)。提出 #71212530 (AC)。何をやって AC になったかというと、答えらしき行列を埋めた後で、事後的に各行各列の最大値が入力の X,Y 数列を満たしているかを確かめている。悔しいなあ。やるべきことはできていたし、実行時間にも余裕があったのに、検算をする慎重さが足りなかった。実装に時間をかけすぎていたことも敗因。大きい値から埋める派と小さい値から埋める派の2つを観測したけども、自分は大きい値から埋めました。小さい値から埋めるときに何を考えるのかはわかりません。「小さい値から行列の要素を埋めていけばよいです。行と列の片方にその値があればどちらかを適当に埋めていけばいいのですが、両方にある場合は交わった要素をその値にしなければなりません。 また、それ以外のその値以下で使われていない最大の値にすればよいです。それにはBTreeSetを使って要素を[first, last)の区間にすればよいです。結果的に区間が隣り合えば結合します」 わかりません。


2025年11月20日 (木) ScanSnap S1500 を処分することにした。純正の消耗部品はもう手に入らないし、消耗部品でない紙送りローラー(4つ)が溶けてスキャンに支障が出ている。ネットで見かけたシリコンチューブを使った方法も試したけど、一時的な延命にしかならなかったし、安定しなかった。紙送りが差し支えると 1 mm の帯が 5 mm、5 cm に引き延ばされたような縦長の画像が出力される。あからさまだとすぐにスキャンし直せるけどあとで読んでいるときに1ページ2ページ横一線に入ったにじみに気がついてももう紙束がなかったりする。エラー率は 20 % から 1 % のあいだくらい。ベストな状態でもゼロにはならなかったし、ベストな状態が何か月も続くわけでもなかった。シリコンチューブはまだまだ十分な長さが残っているけども。あとは紙を差し込んでも全く吸い込まないことが頻繁にあって、パッドとローラーとシリコンチューブの隙間で何がどうなって空回りしているのかわからない。わからないままだましだまし機嫌を伺ってスキャンしてきたのがここ数年のこと。それより以前は角川文庫の紙質を特に苦手にしていた以外はそれなりにうまくいっていた。一度セットしたらあとは放置という具合にはなかなかいかなかったけど。15 年間で 708472 枚スキャンしたらしい (ScanSnap Manager による報告)。もう十分かな。■IX2500 を買うと決めた日がたまたま IX2400 の発売日で、今日まで様子を見ていたけど待ちきれなくて IX2500 を注文した。IX2500 を IX2400 と比較したときの自分にとってのメリットは USB ケーブルが省略できるということのみだけど、販売価格差が数千円なら IX2500 が安すぎるのでそれでいい。15 年前の S1500 の購入価格が 41000 円だったのだから、昨今の物価を考えると IX2400 で5、6万円、IX2500 で7万円でも良心的価格だったと思う。これは販売価格の話。IX2500 の最安は5万円からなので安すぎる。4万でも5万でも懐には痛いし1週間様子を見てきたのではあるけども。


2025年11月16日 (日) [AtCoder] 今日は estie プログラミングコンテスト2025 (ARC210)があった。■A 問題 Always Increasing。直前の要素からいくつプラスされている必要があるかという情報を管理しながらクエリをシミュレートする。実際の提出では増分ではなく数列の値そのものを BIT で管理して無駄に log を付けた。それにもかかわらず BIT だから累積和だからということで勘違いをして、N 番目の値を参照したら N 項の累積和が得られると思い込んで答えが合わなかった。21 分かかっています。■B 問題 Remove Median Operations。1回のクエリをシミュレートすることはできると思うんだけど、クエリ毎にシミュレーションを繰り返していては当然間に合わない。困ったね。先の問題をチラ見して追い返されたりしながら考えていると、数列 B を数列 A に放り込む操作はまとめて行ってもいいような気がしてきた。A と B を混ぜて小さい方から N/2 個、大きい方から N/2 個を取り出して合計したものが答えではないか。それの正しさは X から X の中央値を削除する代わりにマークを付けてシミュレートしていけばなんとなく(!)わかる。あとは昨日の ABC-E と同じように BIT で数と和を管理して答える。それだけのことがすんなりいかないんだな。小さい方から N/2 個と大きい方から N/2 個を得るのに左からと右からで添字を調整してごちゃごちゃするのが嫌で、ソート列を昇順と降順で2つ作って、データは2つだけどコードはコピペで済ませようとした。ところが座圧のためのデータは複製していなかったために結局添字の調整が必要になっていて、それに気がつかなくてデバッグに時間を取られた。#71013020 の 81 行目。Mn↔Mx の交換だけではダメで 77 行目では X[i] だったものを X[~i] にしている。こんな罠に初見でひっかからないはずがなく……。40 分かかっています。■C 問題 Fair Coin Partition。だいたいの答えは出た。最初にどんどん繰り上げていって、大きいコインから順番に M 人に配る。小は大を兼ね、逆はそうではないので、大きいコインを無駄にしないように最初にすべて繰り上げて大きいコインから順番に最大限消費していく。その次が問題。M 枚未満の半端なコインを今度は繰り下げていきたいのだけど、最初に持っていたコインより細かく砕くことはできない。何枚繰り下げることができるのか把握しきれなかった。


2025年11月15日 (土) [AtCoder] 今日はオムロンプログラミングコンテスト2025 #2(ABC432)があった。E までで C が一番難しかった!■A 問題 Permute to Maximize。逆順ソート。■B 問題 Permute to Minimize。昇順ソート……なんだけどゼロ始まりは許されない。正規表現でやろうとして5分かけてしまった。自分は Ruby の置換文字列フォーマットが好きじゃないんだよね。最初に JavaScript で学習したから後方参照(\1,\2...)とかぶっているのが気に入らない。それに文字列リテラルのエスケープ文字として \ が消費されてしまうことへの配慮がないのも問題。だから必ずブロックを与えてグローバル変数としての $1,$2... を参照するんだけど、忘れていました。■C 問題 Candy Tribulation。19 分かかった。ずっと手が動かなかった。大きい飴の数を最大化するというからまずは個数のすべてを大きい飴に寄せた。そこから総重量を揃えるために小さい飴に置き換えていく。その刻みは必ず Y-X ずつなので、まずは不可能なケースとして Y-X で割った余りがすべて同じでないといけない。最も個数が少なく従って最も軽い人の総重量に揃えられるのかな? 個数が多すぎるとできないけども。提出後も半信半疑でジャッジの進捗を見守っていた。WA が出て全く不思議がなかった。■D 問題 Suddenly, A Tempest。大きな海苔を縦または横にスパッと切ってずらす。それを最大で 14 回。2 の 14 乗でもそれほど大きくない。矩形の切断と移動をシミュレートして許されそう。矩形クラスを用意させられているあたりでもう実装が大変なんだけど、まだ後半パートがある。細かく刻まれた矩形の隣接判定と UnionFind がしたい。しかし組み合わせの総当たりは (1<<14)**2/2 > 1億3000万なので許されないと思った。刻まれた矩形の1枚1枚は重なっている部分がゼロのはずで、隣接のしかたは右辺と左辺もしくは上辺と下辺が1差で隣接している場合に限定できるので、X(Y) 座標で分類して Y(X) 座標でソートすれば総当たりの2乗ではなくソートの NlogN のオーダーで判定ができると思った。ところが自分は分類だけしてソートも尺取りもしなかったのでオーダーが改善しておらず最悪で ((1<<14)/2)**2 ≒ 6700 万の計算量で危なかったけど、45 ms で余裕だった (#70980315)。ギリギリの計算量で落とす意図はなかったみたい。■E 問題 Clamp。クエリ2の式の意味を理解するのに時間を要した。なるほど上と下をクリップするのねと理解した瞬間に問題名の Clamp が目に入って悔しい思いをした。式を読まずに Clamp の一語ですべてが伝われば早いんだけど、そういう順番での理解はありえないんだろうな。でも苦労してたどりついた結論が問題名に書いてあるっていうね。クエリ2に罠があります。l と r の大小関係に制約がありません。そういうときはクランプするのに min と max をとる順番に応じた定数になる。問題自体はいつもの BIT で和と個数を管理するやつ。お前 F 問題の常連ではなかったか。■F 問題 Candy Redistribution。N の制約が 20 以下と小さいけど何が難しいのかがわかっていません! たくさんの飴を持っているなら、自分か相手のすくなくとも一方の個数をちょうどにできる。あまりにも多くの飴が足りないなら、複数の人からかきあつめる必要がある。これはどちらも避けられない操作なので差はつかない。差がつくのは余りと不足がぴったり一致している二人のあいだで受け渡しを行うときで、1回の操作で2人が満足する。だからたぶん難しさというのは、たくさん持っている人がうまく分配することで、たとえば X 回の操作で自分を含む X+1 人が満足するケースをどのように実現するかだと思った。まるで見当がつかないので BFS をして経路を復元する方法を書いている途中で時間切れ。BFS のキーはソートして正規化したいけど並べ替えをしてしまうと操作列の復元が難しくなる(不可能ではなさそう)、というところで足踏みをしている。■順位表を見ると 86 分の遅遅5完でも意外に高くて 585 位だった。E 問題を 2294 人が通しているのに対して D 問題を通しているのが 732 人ととても少ない。自分では ABCDE で一番頭を使った C 問題を 4429 人が通しているのはちょっと信じたくない。もっと自分と同じように苦しんでほしかった。■■■D 問題ってもしかしてカットして倍々に増やしていくことってできない?(日曜の朝最初に頭に浮かんだこと) X カットと Y カットがそれぞれ n 回と m 回なら(n+m=N)、(n+1)*(m+1) が精々? 矩形の数が最大で 64 ? 総当たりでもなんでもやれば通るんだ?


2025年11月14日 (金) 20251016 の続き。パスキー。「認証情報のデバイスをまたいだ一元管理とオンライン同期は別の話であって、Google に一元管理させる一手はない」と書いていたこととちょっと関係する話。「「1Password」がWindows 11のパスキー管理ツールに、他デバイスとの同期も可能 - 窓の杜」 オンライン同期プロバイダーという仕組みをマイクロソフトが Windows に用意して、1Password がそれに対応したことで、認証自体は Windows Hello が行うけども、バックエンド部分(同期と、保管も?)を 1Password が担う形に。1Password の評価は保留するけども、他の、アルゴリズムで勝手にアカウントを BAN して何の応答もサポートも得られないという話が聞こえてくるところに自身のアイデンティティを預けるなどできようはずがないので、取り替え可能な仕組みは良いと思う。だけどね、やっぱりね、オンライン同期は余分なんよ。オプションなんよ。Windows の手を借りるのでも Android の手を借りるのでもいいけど、デバイスに認証情報を保存するのが一番で、その段階でオンラインのアカウントに出番はない。Android を使うのにログオンはしないし、Windows を使うのにログオンしているのはローカルアカウントだ。鍵を同期するためにネットワークに持ち出すときに初めてネットワーク上のアカウントと紐付けるのが順番だろうと思う。そして自分はそういう形のポータビリティは求めていない。パスワードをメモした物理メディアがなんぼマシか。他人の介入は不要。


2025年11月08日 (土) [AtCoder] 今日はトヨタシステムズプログラミングコンテスト2025(ABC431)があった。■A 問題 Robot Balance。頭でっかちはダメです。■B 問題 Robot Weight。N 種類のパーツを付けたり外したり。なんかせこい方法ないかなって考えて思いつかなかったから 01 配列を別に持ったんだけど、重さの値を -1 倍しながら足せば良かったんかな。■C 問題 Robot Factory。A 問題の発展。重いボディ K 個と軽い頭 K 個の一意な組み合わせ。これを実装するにあたり、ソート列から重い K 個と軽い K 個を取り出すメソッド(shift/pop)を取り違え、頭と体を比較する演算子の向きを間違えるのが自分です。■D 問題 Robot Customize。B 問題の発展。DP をしたいけど状態をどうするか。頭の重さに対して頭に取り付けたパーツとボディに取り付けたパーツの嬉しさの合計の最大を記録した。頭に取り付けなかった時点でそれはボディに取り付けることが決定しているのでその嬉しさを即座に合算してしまって総合的な優劣を比較すれば良い。しかしこれは TLE×3 だった。計算量を見積もってみると、N=500, sum(W)=500*500 のとき、ループ全体で 500 の3乗(=1億2500万)。頭の重さの最大が sum(W)/2 なのでざっくり半分にして 6250万。これは Ruby には厳しい。ここで見かたを変えて、ボディに取り付けた場合の嬉しさはただで手に入る嬉しさであり、頭に取り付ける場合は重さにハンデを抱えるけどボディに取り付けた場合の嬉しさにさらに嬉しさを付け加える行為だと考えた。そうするとボディに取り付ける場合の嬉しさは必ず得られるベースラインなのでいちいち計算して比較する必要がなくなる。頭に取り付ける場合の嬉しさはボディに取り付ける場合よりどれだけ大きいかで評価されるので、そもそもボディに取り付けた場合より嬉しさが低いなら頭に取り付ける理由がないとわかってループが省略できる。よく知らない用語を雰囲気で使って説明すると、2か所からもらう DP をしていたものが1か所からもらうだけで済むようになった。実際の計算量は入力の傾向に依存するような気もするけれど、これらでおよそ半分に時間が節約できて AC になった (#70786365)。他の言語では必要のない苦労だったかもしれない。入力の傾向に関係なく状態空間のサイズ(と遷移)に応じた決まった時間で答えが出るのが DP であるので、何をやってもそれは定数倍の改善か入力依存のアドホックな改善でしかない。■E 問題 Reflection on Grid。同配点の F 問題も一応読んだ。トポロジカルソート的な感じで場合の数を数えたいけど「徒競走」に比べて制約が大きすぎる。見込みがないと思って E 問題に専心した。その E 問題。重実装の気配がビンビンしています。それどころか実装に取りかかれない。これは頭を使う必要があるなと一度立ち止まって考えることにした。盤面のマスの数が多すぎるので1マス1マスああしてこうしてと試行錯誤することができない。1か所変更してみた結果青木君に光が届くかが即座にわかると仮定してみたら答えられるだろうか。たとえば初期盤面の経路の1マス目を変更して結果を見る。ダメなら1マス目はそのままにして2マス目を……。これの何がダメか。盤面の外に飛び出さない限りおよそどんな経路を選んでも青木君にはたどりつく。ただし操作手順が増える。操作手順の少なさが問われているのに手数を度外視した解法はいけない。方向を加味して盤面を4倍した状態を持つということは考える前から決まっていた。BFS をしたいですね? 手探りで書いているこれは 01BFS ですか? 提出 #70805678 (AC)。1時間あっても完成しなかったからこれは終了後の提出。鏡の向きの変更を記録して考慮しないでいいのはなぜか。一度鏡の向きを変更して進路を変えたマスに紆余曲折の末再進入するケースを考える。鏡の向きを変更することで3方向どれでも好きな進路を選べるわけだけど、過去に左から入ってどこかへ出て行っていた場合、再進入して左以外のどこかへ出て行くケースは紆余曲折を省いて最初の進入時にそこへの進路を選んでいたことにすればいい。左側に出て行きたいときは? 他の経路を通って初めての進入が左側以外になったときに考えましょう(そのように取り扱えるようになっています。そしてどんな紆余曲折をたどっても U ターンして左方向へ出ていく経路はないのでこれ以外のケースは想定しません)。


2025年11月04日 (火) 楽園 Le Paradisが刊行停止を発表、2026年2月発売の次号第50号が最終号 - コミックナタリー」■悲しい。4号から買い始めて全部持ってる。雑誌で読みつつコミックスも買う作家さんも、コミックスを買うタイプではないけど雑誌では面白く読む作家さんも(すまない)、ほぼすべての連載陣がどちらかであって、奇跡的なコストパフォーマンスを誇る雑誌だった。匹敵する漫画雑誌をコミックエール!しか知らない(そちらは 12 号で終わってしまった)。刊行ペースを上げずに無理せず長く続いていると思っていたけど、50 号で終わりかあ。


2025年11月01日 (土) [AtCoder] 今日は AtCoder Beginner Contest 430 があった。■A 問題 Candy Cookie Law。人間は記号で記述された論理よりも法律やら違反やらの意味で具体化された論理の方が答えやすいらしいですよ。だからといって違反しているときに Yes と答えさせられるのはちとやっかい。前提条件をそのままに判定をひっくり返す。もしくは問題文の通りに判定して No を出力する。■B 問題 Count Subgrid。いつもやっているように指を使って数えたにもかかわらず記述を (N-M+1).times (0 から N-M までの繰り返し) から [*0..N-M+1] (0 から N-M+1 までを値とする配列) に書き換えたときに off-by-one エラーを仕込んでしまって合わないサンプルに困ってしまった。デバッグプリントで解決。■C 問題 Truck Driver。しばらくわからなくて目の前に沼が広がって見えた。今日はここまでかと。2つの条件に合う範囲をそれぞれ二分探索で求めて考え合わせる。気がつけばこれだけ。■D 問題 Neighbor Distance。お隣さんがわかれば差分更新できる。SortedSet がないから BIT で管理するんだけど X の値が大きいので座圧が必要。今でこそ座圧なんてやるだけ面倒なだけに見えて制約で手軽にいじめられてるなこのひと手間必要でしたかなんて考えてしまうけど、「座標値(-10^9 以上 10^9 以下の整数)でなく座標値の序列(N個以下とM個以下)でグリッドを作るって発想が出てこないんだよなあ」なんて初々しい感想を書いていた時期が自分にもありました。座圧ができれば橙 diff の F 問題「. (Single Dot)」が解けた時期が AtCoder にはありました。WA になった最初の提出まで 24 分かかってるんだけど、実装に取りかかる前に強制うんこ休憩に襲われて急いで E 問題を読んで駆け込んだのだった。なお E 問題のロリハ方針が決まってもまだ出られなかったもよう。WA の原因は番兵が小さすぎたこと。番兵との距離が1しかないならいないはずの番兵との距離を答えに計上して間違える。修正に2分。■E 問題 Shift String。入力が素直に2進数に見えるのでハッシュ値を比較するのもハッシュ値を差分更新するのも自然に行えると思う。マルチテストケースであり問題の見た目から基数に2が選ばれやすいだろうから、ありがちな素数の組に対してハッシュの衝突が狙いやすいと思ったけど、AtCoder で最も有名な2つの素数を使っていても大丈夫だったみたい。■F 問題 Back and Forth Filling。50 分弱残して解けなかった。似た設定でこれより答えやすい問題を見たことがある。自分の左右に最低いくつ最大いくつの数があるかを DP で求めて BIT で区間 add をすれば答えの C 数列が得られると思ったけど、サンプルが合うところまでいかなかった。■コンテスト成績証。737 位、1502 水パフォ。■■■F 問題。昨日はこう書いた。「左右に最低いくつ最大いくつの数があるかを DP で求めて……」。最大でいくつの数が置けるかを管理する必要はないのだった。最低限必ず置かなければいけない数がいくつあるかだけで良かった。前から4変数、後ろから4変数で DP をしていたものを、前から2変数、後ろから2変数に書き換えたらするっと答えが一致した。BIT もいらなかった。変化量の累積和で十分。提出 #70649443 (AC)。■■■@2025-11-11 ABC431 の結果が消えていて、ABC430 の結果は順位が同じまま 1587 パフォに上がっている。何があったんだろ。