/ 最近 .rdf 追記 設定 本棚

脳log[2026-03-02~]



2026年03月02日 (月) [AtCoder] 今日の AWC 0016 Beta。とりあえず長さ N の数列を与えておけばいいと思われている節があります。全然ケチをつけるところがないんだけど、今日は1つだけ。「荷物運びの道」。コメントに書いて提出した(#73778547)。「i = 0 # S のインデックス。これがスタート地点 s と一致すると読んだが(「高橋君はある倉庫 s(1≤s≤N)からスタートし、荷物を持っていない状態で東へ向かって倉庫を順に訪れます」)疑っている。」「サンプルが合わなかったので、基準値 S[i] を S[s-1] とする。つまり、スタート地点の荷物を拾うということであり、何も持たないで東へ向かう時間は存在しないということだ。瞬間というのを幅ゼロの時間だと定義すればそういう瞬間はあったのかもしれないが、そんなことを言い張るやつは存在を抹消されても文句は言わせない。」■やっぱり日本語の問題になるんだよな。最初は「右向きで一列ってどんな状態?」「握手とは」「時間の単位」「すなわち」がひっかかったし(20260212)、その次は「負の枚数のコインを得るゲーム」が人間にはない発想でおもしろかった(20260224)。今日はスタート地点にある荷物を必ず拾うというときに、「荷物を持っていない状態で東へ向かって」と表現することはありえないということを書いた。今読み返すと今日もすなわちに続けて「倉庫 s からスタートした場合、高橋君は倉庫 s,s+1,s+2,… を順に訪れ、累積の荷物の重量 As​+As+1​+⋯」と書かれてあって、そこで初めて問題を解く情報が揃う状況ではあったらしい。■すでに明らかではあったことをもう一度書くと、AI 作問に対する適切な態度とは、冗長な文章から必要な情報だけを拾い上げ、蛇足、論理の飛躍、不適切な言い回しなど、無視しなければいけないものを素早く無視する能力が一番問われている。じっくり読んでも困惑が深まるだけで馬鹿を見る。だけどこういう読み方って、自分にとって都合のいい部分だけを都合のいいように読む読み方と同じであって、こういう読み方ばかり訓練されてこれしかできないと問題よ。


2026年02月28日 (土) [AtCoder] 今日は AtCoder Beginner Contest 447 があった。■A 問題 Seats 2。シート数が奇数の場合は半分より多くの人を座らせられる。+1 してから 2 で割って切り捨て。■B 問題 mpp。Ruby は tally メソッドが便利。■C 問題 Insert and Erase A。最初に split メソッドが浮かんだのでそれをどう使うかを数分考えていた。つまり、/(A+)/ で split するのか /([^A])/ で split するのかということを。あとは入力によらず処理を統一するために入力の頭に必ず A を付加し、末尾に必ず AZ を付加するなどした(答えは変わらない)。そうすると split(/([^A])/) した結果が必ず偶数になって都合が良い。S と T をそれぞれ split して、偶数番目の比較で判定ができ、奇数番目の比較で答えが求まる。abs を付け忘れてサンプルが合わない。11 分かかったので D 問題より難しい。■D 問題 Take ABC 2。D は DP の D……ではありませんでした。ただの貪欲。最も左にある i を使用しない理由がないし、そのときに、i より右にあって最も左にある j を使用しない理由がない。最初に入力をスキャンして A、B、C に対応した i,j,k の列を用意しておいて、前から順に使えるものを使っていく(#73691658)。事前準備なしのバージョンはもっとシンプル(#73746369)。A の数と AB の数と ABC の数を管理しておき、A への遷移、A から AB への遷移、AB から ABC への遷移を文字列に沿って実行する。■E 問題 Divide Graph。辺のコストが倍々になっていくというのが特徴。この特徴をどう読めばいいのかは chokudai さんの典型に関するブログで読んだ(「競技プログラミングの強みと「典型力」について - chokudaiのブログ」)。つまり、大きい方から見てある辺を選ばないで済むのなら、それより小さい辺をすべて選んでもコスト的に見合うということだ。こういうことを書くのが今回初めてというわけでもない。初めてのときは二進数になぞらえて理解してなるほどねと膝を打つ様子を書いたと記憶している。さておき、じゃあソートして UnionFind だねというのが考えずにわかるんだけど、結局実装して提出するまでには 20 分かかるんですね。サンプルで気づいた見落としは、あるボーダーラインがわかったとして、それ以降のすべての辺を必ずしも選ばなくてもいい、ということ。その判定をするためにはボーダーラインを見つけるための UnionFind を寸止めの状態に保つ必要があって、そのへんでごちゃごちゃと場合分けが増えて時間を食った。■F 問題 Centipede Graph。以前にも似た問題があったかな。アルカンの問題。今日は両端の水素が1つずつ少ない。末端から積み上げていく DP を最初は検討したけど、積み上げていく段階では答えが出せない。全方位木 DP ってこと? 結局はトップダウンで実装をしてそれがやりやすかった。まずコアとなる頂点を1つ決める。隣接頂点ごとにどれだけムカデの体節を伸ばしていけるかがわかれば、あとは最長の2つを選んで組み合わせたり1を足したりなんだりごちゃごちゃやって答えが求まる。「どれだけムカデの体節を伸ばしていけるか」を効率良く求めるのはメモ化再帰で実装した。一度の呼び出しで答えをすべて用意することはできない。呼び出し元を呼び出し返すことができないからだ。少なくとも2つの隣接頂点から呼び出されて初めてメモが完成する。かといって隣接頂点リストを呼び出しのたびに何度も走査すると星形グラフで死ぬので、リストは破壊的に消費することとした。一方向にどれだけ体節を伸ばせるかと、体節と体節を組み合わせて全長がいくつになるか、どちらも答えが1通りや2通りではなく計算が間違いやすくなっている。25 分で1ペナを出して、5分で修正して AC。実装がトップダウンで素直だったから凡ミスしかないと確信できたし読解もスムーズで頭から一読してバグが見つかった。時間が 20 分余ってしまった。625 点の G 問題にできることはありません。真ん中2つの使い回しが総当たりできるならなんとかなるかもしれないけど(トップ4)、それができないのではね。■自分のすべての提出コンテスト成績証。瓦増えず。■F 問題。自分の実装(#73718005 の 18 行目)にバグがあると思ったけどバグはなかった。トップ2をメモして答えに利用しているのだけど、要素数が2のときの順序が追加された順で不定。でも要素数が2しかないときは答えが定数なのでセーフ。こんなのが原因で WA になったらリカバリーできないぜ。あと、他の人の提出が UnionFind とか直径とかいろいろ謎。次数が3以上の頂点だけのグラフを考えるのだろうか。いや4以上。端っこの処理が難しくない? あとたぶんボトムアップで積み上げる木 DP でもやっぱりできるような気がしたな(全方位木 DP でなく)。2通りを数える必要があって、自身が中間の体節になる場合と、一方の端になる場合の両方を考えていくことで、行って戻る全方位でなく行きっぱなしの道中ですべての答えが列挙できる(たぶん)。■■■F 問題。ボトムアップで積み上げる木 DP バージョン。たいへん厳しい。じっくり丁寧にコメント付きで書いたけど WA×34WA×25 のち AC。大枠はさっき書いた通り、自身が末端になるケースと自身が中間ノードになるケースを数える。それが WA×34。忘れてはいけないのが、自身が末端かつ唯一のノードになる場合で、必要な子の数が1つ減るので答えがゼロかイチかが変わってくる。それで WA×25。さらに、親に伝える数字には親を勘定に入れてはいけないけど、自身が答えを作るときには親を子の1つとしてカウントすることで他の子の要求数を減らすことができる。値としては同じものが含まれるとしても親に伝えるものと自身で使うもの、7つも8つもの数字を頂点ごとに取り扱って考え漏らさないのはとても難しい。一度 AC を出した後でよくよくわかっていても間違えるのだから、実装方針で当たりを引くという幸運があったのだとよくわかった。


2026年02月26日 (木) これまで何度も同じ議論のたどり方をしてわかりえない人がいる。どういう風か。たとえばある対象が割合の高い順に A、B、C、D の4タイプに分かれるとする。そうすると A に対応しているのは当然のこととして、B や C をにらんで備えておくことで大体8割9割は安心できるな、というような考え方を自分はする。そうすると自然と、「B の場合は」「C の場合は」という論調になる。それに対して、こちらの言い草をまねしてお株を奪っている風なのがまた腹が立つのだけど、「でもそれが問題にならない A (もしくは D) のケースもあるよね」という反論をしてくる。問題のないケースは問題にしてないんだ、こっちは。全体として問題がないように起こりそうな問題を提起してるんだ。「最善のケースもある」「幸運なケースもある」なんてことを俺は言ってないし聞きたくもないのに、それで何かやり返した風を吹かせるからこちらは言うことがなくなってしまう。■直近にあった身も蓋もない話。紙に www 付きの URL が印刷されているにもかかわらず今年に入ってからサーバーの設定が変わってしまったのか www 付きだとアクセスができなくなった。自分が以前から使っていたブックマークには www が付いていたから、名前解決ができていないということなのか 404 すら返ってこないでアクセスができなくなった。「たいへんだ、ページがアクセスできなくなってる」と話を持っていってやがてわかったことは、「以前と変わらずアクセスできるブックマークもある」「どうやら www の有無が関係しているらしい」ということ。「問題だね、直さないとね」というのが自分の意見だけど、それに対して「www を取ればアクセスできる」「検索すればアクセスできる」しまいには「www ありなしどちらでもいいというのがわかりにくい」「1つだけなら(一方がアクセスできないという)問題も起こらなかった」ということを言う。自分にはそのどれもが「だから何だ」としか思えないのだけど、そう言って満足している人にこれ以上何が言えるのか。補足。アクセスしているのは管理ページではないのです。公開ページなのです。誰に www を取れと要求しているつもりなのか、自分がインターネットショートカットを書き換えて済む話ではないのです。■このときに知ったのだけど Google Chrome はプロトコルだけでなく頭の www. も省略してアドレスを表示するらしい。だから同じように example.com とアドレスが表示されていても、ページが表示できていたり(example.com にアクセスしている)、できていなかったりする(www.example.com にアクセスしている)。自分が使う Firefox にはそういうごまかしや視認性を下げる装飾(URL の特定の部分を薄くするとか)は一切させないけど、www があってもなくてもどうでもいいようなものだという見かたは否定しない。だからこそ **www を省かなくてはアクセスできない** という現状はアホの極みだと思うんだよね。伝わらないんだけど。


2026年02月25日 (水) のちみちみんななすんらのなてらもらしらとなくらなくらな」。1時間で忘れると書いたけど、22 日も覚えていられたらしい。今日の原因ははっきりしていて、PC のスリープを解除してからキーボードをウェットティッシュで拭いたせいです。


2026年02月24日 (火) [AtCoder] 3回目4回目以降は普通で特にコメントするところのなかった AWC beta。12 回目の今日はネタが複数。「迷路からの脱出」。サンプルが 10 個あるんだけど、同じのや似たようなのばかりで解答例が 0 と 1 しかない。つかえねー。「石渡りゲーム」 負の枚数のコインを獲得するゲーム。制約の都合で常識外れな値をとることがあるのは AtCoder あるあるだけど、負の枚数とはコインという概念がゆらぐ。そしてこれもサンプル。サンプルがありません! これまでちょっと AtCoder に甘えすぎていたかもしれない。サンプルが弱いとか不平をこぼすくらいなら自分で強いサンプルを作るべきなのだ。それを教えてくれるまさかのノーサンプル。


2026年02月23日 (月) HalMat4194304 (@mat4194304): "ChatGPT『Ruby の Array#shift は「先頭を取り除き、残り全要素をずらす」ので、1回が O(配列長)』 へー5年やってて初めて知った | nitter」■嘘だよ。読んでね。真意が皮肉だとしても誰も得してないよ。「ruby/array.c at master · ruby/ruby」 8910 行目に rb_ary_shift_m の名前があって、rb_ary_shift_m を見ると無引数の場合は rb_ary_shift を呼んでいるのがわかる。rb_ary_shift を見ると rb_ary_behead を1を引数にして呼んでいる。rb_ary_behead を見ると要素が埋め込まれている場合と ARY_DEFAULT_SIZE (16) 未満の場合に MEMMOVE でずらしているけど、これはサイズが小さいときの例外で多くは ARY_INCREASE_PTR と ARY_INCREASE_LEN というマクロで済まされている。このマクロはもちろん線形時間を要するものではない。■ところで Enumerable#each_cons はなんか幅に比例した時間がかかるみたいで配列のスライスではないんだよな。Enumerable モジュールが Array#each しか利用できないとしても線形のメモリと時間で済ませられると思うんだけど(尺取り)、実際は二乗レベルの時間がかかって TLE の原因にしたことがある。■ここまで ARC215 開始 30 分前から大急ぎで。■■■この提出 #73509846 が TLE になる原因かあ。ローカルで TLE になるほどのダメケースを作成することはできてないんだけど、別の問題への自分のこの提出 #61559311 が TLE になるのと同じ理由な気がする。つまり、Array#shift と Array#[]= の組み合わせが配列のコピーを引き起こしているのではないか、という推測。このスクリプト(a.rb)がまともな時間では完了しない一方で、代入を取り除いて shift のみだと普通に実行が完了する。Array#shift (に限らず配列のスライスとその後の変更)が要注意なのはその通り。それを今の今まで忘れていた。■よく読んだ。shift はサイズが特に小さい場合を除いて配列のスライスによって実現されており実体の共有が前提になっている。一方で pop はそうではない。実体を共有したあとでも shift/pop を繰り返して問題はない。さらには条件付きで push も問題を起こさない。しかし要素変更([]=)は実体を共有しているときに必ず共有解除(コピー)を引き起こして問題になる。■これを shift & modify パターンとして、実体の共有化非共有化を往復することでコピーを繰り返している現状を防ぐことはできないのかな。スクリプトは1つの実体しか必要としていないのに無駄にコピーを繰り返しているのだから、コピーを省略できる条件があると思うんだよな。rb_ary_cancel_sharing が ary_make_shared の逆をできる条件がありそうなものだけど、できない理由があるのだろうか。あるいは要素変更のときに共有バッファを専有しているときの処理を追加できないだろうか。配列を切ったり貼ったりするのではないただの書き込みが線形時間を要するというのはやはり予測が難しい。ないならないで array や vector と同じように先頭要素を指すポインタに相当するものを管理するだけなのに、使いやすい shift があるばかりに shift の使用が罠になってしまっている。


2026年02月22日 (日) [AtCoder] 昨日の AtCoder × Engineer Guild オンサイトコンテスト ~ACからはじまる27卒キャリア~予選 (ABC446)。最初に言いたい。コンテスト名が長すぎる。なぜこれを言うかというと、コンテストが始まってみるとなんか見た目がいつもと違うのだ。ページトップの黒帯の幅がいつもより大きくて、[トップ][問題][質問][提出][提出結果][順位表][コードテスト]という重要リンクを覆い隠してしまっていた。AB 問題の提出に6分かかってるのはこれへの対処と動揺のせいが半分。ブラウザを横にちょっと広げたら解決した。■A 問題 Handmaid。以前にも書いたけど Ruby で大文字化小文字化に対応するメソッド名がまったく覚えられないうえに当てずっぽうもことごとく外すので今日は最初からリファレンスを見た。String#downcase, String#upcase が正解。JavaScript が toLowerCase, toUpperCase なのは知ってるんだよ(それが原因か?)。■B 問題 Greedy Draft。ジュースがあるかないかのフラグを管理する。■C 問題 Omelette Restaurant。難しい。他の人の提出を見ると、玉子の日にちを個数個分キューに入れて使用をシミュレートするのがわかりやすかった。そういうことを可能にする小さな制約なのは目に入っていたけど、制約に対応した解法を新しく考える手間を惜しんで突き進んでいった。自分はどうしたか。B 数列(玉子の使用数)の累積和を用意して何日目までに何個必要かを二分探索できるようにした。玉子が補給されると、これまでの玉子で満たされている要求量から何個上積みして要求を満たせるかが、累積和の値(玉子の要求量の累積)と添字(日にち)から二分探索で判断できる。でもややこしいので方針ミス。18 分かかった。■D 問題 Max Straight。これは3分半。Hash で値をキーにしてその値に至るまでの要素数の最大値を記録した。■E 問題 Multiple-Free Sequences。とっかかりもつかめない。飛ばした。■F 問題 Reachable Set 2。最大のミスは無向グラフについて問題を解いていたこと。自己辺も多重辺もあると気づいていたけど有向グラフであることが頭に入っていなかった。そのせいで UnionFind を使う頭から離れられなかった。あとなんか削除する辺の数を答えようとしていた。答えるのが頂点数なら自己辺も多重辺もほぼ無視できて考慮に値しない。終了後もずっと UnionFind をいじくっていたけど、この先に答えはないとやっと頭がリセットできると、k=1..N に沿って寸止めの探索を進めていくだけだった。提出 #73515718 (AC)。訪問済みの頂点(k 以下)と訪問を先送りしている頂点(k より大きい)を2つの Hash に記録すると、それぞれのサイズが判定条件と答えになる。これが 500 点は買いかぶりだと思うけど、解けなかった人間が言うことではない。■■■E 問題。他所で functional graph だと読んだ。それだけではわからない。この問題は M の倍数だとか無限数列だとか言っているけども、ポイントは mod M で考えてもいいということだ(昨日はそれがわからないんだなあ)。そうするとある項は前2項によって規定されるけども、ある項の取り得る値は M 通りで、行き先は M×M 通りの組み合わせによって決められる。行き先が有限だから必ずどこかでループに入る。それが functional graph ということだろう。ここからじゃあどうやって実装しようかなと考えるんだけど、M*M 通りのメモ化再帰でいいでしょう。提出 #73532574 (AC)。時間内に解けてほしいなあ。■■■スペースが足りない。今日の AtCoder Regular Contest 215。■A 問題 Zombie。ちょっと楽しい問題。一見すると全然とっかかりがないように思える。餌を置く位置や順番が影響しそうで途方に暮れそうになる。でも実はゾンビとゾンビのあいだに餌を置いたとき起こることは、2体のゾンビがくっついて空間が消滅し、その他のすべてのゾンビが間隔を保ったまま中央に寄ってきて、左右の端の空間が広がっている、という割とシンプルな状況だった。じゃあ左右端の空間が狭いあいだはゾンビとゾンビのあいだの空間を消費して、左右端の空間が十分に大きくなったら左右端に交互に餌を置くのが良いのではないかと思った。でもサンプルがいくつか合わなかった。整理するとわかるのだけど左右端の空間を L、R とするとき、端に交互に餌を置いて稼げる時間は L、R+L、R+L、R+L、という感じでほぼ一定で推移する。左右端の空間をどこまで育てるのが最善かは単純な大小比較ではわからないのだった。餌の数 K は 10^9 と非常に多いけど、ゾンビのあいだの空間は N-1 までに限られている。全探索をした。提出 #73535514 (AC / 422 Byte / 400 ms)。■B 問題 Stolen Necklace。2つの集合を管理してやるだけですか? と思ったところで「仕切りの個数 K は N 以下である」という条件に気がついた。これが難しいのだろうか。でも 1 1 2 2 3 3...N N という、一番仕切りが必要になりそうなケースでも仕切りの数は N 以下に収まっているようだったのでとりあえず投げてみて AC だった。提出 #73537550 (AC / 376 Byte / 385 ms)。■終わり。


2026年02月21日 (土) 【備忘録】運転免許証一体型マイナカードを期間内で早めに更新したら免許紛失扱いになった話|破綻国家研究所」■いきなり機種変更をするとおサイフケータイで利用している電子マネーの残高が引き継ぎできないから変更前に手続きをしてねという話に見えました(小並感)。この人は役所に免許証のことを伝えているにもかかわらずこの結果では、マイナンバーカードの取り扱い窓口としての役所の対応がこなれていないというか無責任というか、そんな感じ。スマホを(間接的に)売るケータイショップがスマホのサポートを(有料かもしれないけど)投げ出さないのを見習ってもらいたい。■後半に「マイナンバーは「番号」であり、カードは媒体です」と書いておられるけども、これはちょっと誤認があると思った。番号は個人の識別子ではあるけども、あなたがその番号で特定される個人であることを保証するものではない。一方でカードは、その所有と PIN の組み合わせによってあなたがそのナンバーとカードで特定される個人であることを証明することができる。カードは番号の媒体にとどまる存在ではないのです。あえて言うならあなたの代理人となりうるものだというのが自分の理解。代理人という言葉を自分は借金の連帯保証人と同じようなものだと思って使っている。あいつは俺で俺はあいつだからどんな言い逃れもできないという意味で。■ただちょっと思うのは、新しいマイナンバーカードがあっても警察の方で免許証連携の引き継ぎができなかった、あくまでも旧カードが必要というのが理解できなかった。マイナンバーカードを新しくしたからといって別人になるわけではないのだから、旧カードでも新カードでも免許証をくっつけるのに何の違いがあってできるできないという話になるのかわからない。免許証連携をしたマイナンバーカードが仮に同時に2枚存在するようなことが生じたとして、何の問題もないと思うけどどうなんですか。■警察は免許証をマイナンバーカードに準じたレベルで個人を特定して発行しているわけではないということ? 理論的には誰かの免許を誰のマイナンバーカードにもくっつけることができる? それを完全には防ぐことができない? だからせめて唯一性を保証したい?


2026年02月20日 (金) [B! Togetter] 嫁の「48個のイチゴが届いたけど全部4分割したら何個になる?」という質問に4歳の子供が192個と即答してた、解法を訊いたら「4096の次は8192だから」と言って嫁を困惑させてた」■ブコメで複数の嘘松認定が見られるけども、当のページを開いたら1ツイート目がいもす氏のものだった。馬鹿の自己紹介はいらないんだよなあ(コメントに対して)。コンプレックスがあるからこそ騙されないぞと予防線を張りたがるのかなあと想像します。


2026年02月18日 (水) せこい話。■新しく開けたこのキッチンペーパー小さいな正方形ではないなと気がついたときに、予想してパッケージを眺めたら案の定、「100 カット」という文句で内容量が表記されていた。正確なサイズ表記がないわけではないけど、でも表に複数書かれていたのは 100 カット。紙を計るのに長さ重さ以外が役に立ちますか。■ケータイ会社が無期限繰り越しって言い始めたあたりから騙したもん勝ちみたいな風潮がある(これのからくりは繰り越し上限額が高々2、3か月分に制限されていたが隠されていたこと。期間ではなく額で制限しているときに無関係の期間を持ち出して無期限とふれこむ面の皮の厚さよ)。「50%割り引きます (ただし割引上限500 円)」みたいなのも当たり前になっていて、もはや何も響かない。見えるところには真実がない。■アマゾンで売られているみかんに対照的な2つがあって、「箱込10キロ (9kg+保証分500g)」と「10kg(+約0.5kg多め)」というもの。これって要は多少多めに入れとくからちょっと悪いものがあっても勘弁してなという意味合いの 500g だと理解してるんだけど、前者の「箱込み10キロ」はうっかり者を引っかける目的以外では書くべきではないことを書いているのであって、騙す意図しかない。無能で説明できることに悪意を見いだすべきではないと言いますが……(どっち?)。


2026年02月17日 (火) やっぱり自動車は自転車を追い越せない!? 「驚愕の新事実」その後と規制見直しの行方|自転車ライフの情報サイト「SHIFTA MEDIA」」■自転車の追い越しに関する追加ルールの話を知らなかった。青切符と同じ4月からだって。だけどその内容は別に新しいものではなかった。もう 20 年以上前だけど、自転車を追い越すときは徐行するか十分な間隔を空けるって習った気がします。新ルールがそれとどこが違うのかわからない。ひょっとすると自分の記憶は路側帯の歩行者自転車の話だった可能性がある?■記事の主旨と同じ関心は自分も以前から持っていて、オレンジラインをまたぎたくないばかりに自転車のすぐ横を無理に抜けようとするのはアホのやることだよなと、法よりも人間と自分の判断を優先する人間は考えるのでした。交通ルールは予測可能性によって安全と効率を図るものだと思っていて、ルール違反は予測可能性を損ねることによって他者が関わる安全を危険にさらす可能性があるけども、それは目の前の自転車に接触するかもしれないという今まさに存在している危険に優先して考慮することではないと考えるのだよね。じゃあずっと自転車の後について走るのが誰にとっても一番安全だって? そこは取り締まられる危険と天秤にかけて自己責任で、見えてない他者の潜在的な危険には目をつぶって自転車の安全と自分の効率を優先します (すぐ前に車の列や止まれや赤信号が見えているなら追い越ししないのも合理的な選択になります)。


2026年02月15日 (日) [AtCoder] 昨日は AtCoder Beginner Contest 445。愚痴と嘆息しか出ないので長くは書くまい。■A 問題 Strong Word。先頭と末尾の文字が一致することと Strong がどう結びつくのか、わかりません。■B 問題 Center Alignment。問題文を3度読んでも4度読んでも何を言っているのかさっぱりわからなかった。サンプル入出力をチラ見して雰囲気を掴んでからまた読んでみて、それでもなかなかわからなかった。脳みその盲点をつくようなフォーマットで書かれていたとしか思えない。奇数長の文字列の左右に同数のパディング文字を補って、すべての入力を同じ奇数長の文字列に整形する。Python をメインにしている人の提出で知ったんだけど String#center というまさにこのためのメソッドが Ruby に存在していた。いつからの新参なのかとリファレンスを遡ってみたら、Ruby-1.8 時点ですでに存在していた()。1999年発売の『オブジェクト指向スクリプト言語 Ruby』のリファレンスを見てもやっぱり載ってる。完全に J(ava)Script における String.prototype.strike メソッドや String.prototype.anchor メソッドの類いだとみなして無視していたな。全く存在を認知していなかった。■C 問題 Sugoroku Destination。今回の問題児。解けなかった。10 の 100 乗回移動するという。いわゆる「非常に大きな数」であり具体的な数値に意味はないのが通例だけど、この問題ではどうか。ループがあるならループのどこで停止するかは1、2の差が影響する。ループがないように値の範囲に制限があるかなと制約を見直したけど、特に制限はなかった(←間違い!)。問題文を読み返しても特記事項はなかった。10 の 100 乗のビット長を出力してみたら 300 とちょっとで、意外に少ないと思ってしまった。でも TLE だった (#73298781)。300*N≦1億5千万だから、Ruby には桁が1つ多い。日が改まってから他所で i (アイ) と 1 (イチ) だと読んでもう一度問題を開いたけど、最初はやっぱりわからなかった。目をこらしてやっと Ai の下限が i だとわかった。決して老眼ではないんです。室内用の眼鏡は 15 年以上前に作って5年以上前に一線を退いた度の合っていない眼鏡なんです。視力検定、注意力検定はやめてね。AC (#73346461) と TLE との差分はステップ数が 10**100 か N かという違いだけ。いち早く AC を出していた人の提出によると、より最適な解法は数列を逆順に一度なめるだけらしいです。UnionFind の Find 関数を根に近いところから呼び出していくから再帰が必要ない、みたいな流れ。鮮やか! そうだよな、C 問題だもんな。■D 問題 Reconstruct Chocolate。貪欲です。候補となるピースをソートしたけど、実はソートはいらない気がしてきたな。どうだろ。■E 問題 Many LCMs。答えは合います。時間が間に合いません。TLE×18TLE×16。要素を1個省いたとき、その要素が全体の LCM にどれだけ寄与しているかを計って取り除く(割る)。そのために素因数ごとに最大の指数と2番目の指数を記録した(1位2位が同値の場合は同じ値を記録する)。最大の指数をまとめあげたものが LCM になる。取り除く要素が最大の指数より小さい指数を持っているならその素数に関して LCM への寄与はゼロ。最大の指数と同じ指数を持っているなら2番目の指数を参照してその差分だけが LCM に寄与している。緑 diff で最後の最後まで解けなかった Coprime もそうだったんだけど、とにかく時間が厳しい。やり方はいろいろあるけど間に合うものがほぼない。Ruby におまかせの require 'prime'Integer#prime_division とか、約数列挙とか、素数を列挙してからの試し割りとか、だいたい通らない。だけど絶対に通らない問題というのは数えるほどしかないし(少ないけどあります)、うまいやり方で余裕で通す人もいたりするものだから、結局は己の至らなさにはね返ってくるのであって、不満のはけ口はありません。残念。精進しような。■D 問題。Ruby で一番最初の AC であるこちらの提出 #73307835。答えの座標が X と Y のどちらか一方が1に固定されている。なんでそれでいいのかわからなくてスクリプトに手を加えてピース番号をグリッドにプロットしてみたけど、番号に重なりはなかった。全然わからない。……。お風呂でイメージしてきた。(1,1) から遠いところから切り落としては全体のサイズを縮めていく、という過程を考えれば、どのピースも (1,1) から右または下にどれだけ離れているかという尺度で特定できる……らしいですよ。■E 問題。Ruby で最初の AC がこちら (#73334218)。require 'prime' しないで素数の倍数に素因数をメモすることで素数を列挙している。自分は素数を判定する方法としてこのやり方を知っているけど、素因数を列挙するための情報源としての利用法は知らなかった。素数ではない(合成数である)数のスロットには素数のひとつが記録されていて、それにより自身が素数ではないことが知れる。それだけではなかった。ここで合成数を n、記録されていた素因数を p として、n = n/p を繰り返して n が 1 に至るまでには素因数の指数の和と同じ数のステップが存在し、その過程ですべての素因数を指数個分ずつ拾い集めることができる、ということらしい。すご。■まねしたのに通らへん。提出 #73350310 (TLE×2)。書き方か。step メソッドを while ループに書き換えたら通った。提出 #73350361 (AC / 1830 ms)。やはり while。while 文は(ブロック付き)メソッドより速い。■F 問題 Exactly K Steps 2。何重にも重なったループを書こうとして書き切れなかったけど、行列の文字が見えたら行列の掛け算をイメージしてループを書く助けにできる。提出 #73353560 (TLE×22/AC×21)。ダメです。行列計算は N の3乗だったような気がしますが、log(K)N^3≦3000万で通りませんか。F 問題で行列計算やるだけは考えが甘いですか。■E 問題の高速素因数分解に関連して ABC177-E の解説が挙げられており、それがまさしくさっき言及した Coprime の問題だったんだけど、えっと、自分はまだこの緑 diff の問題を通しておりませんでした。緑埋めをしているときに埋め切れず、水埋めをしているときにも何度もふりかえってははね返され、そして現在に至る。もう諦めて忘れてしまったみたい。■精進。ABC177-E「Coprime」。Coprime と名の付く類題に至るまで苦手意識を植え付けられたいわくつきの問題。Coprime 恐怖症の元凶。今日最初に書いた解答は ABC445-E にならって素因数分解をしてからそれを使って判定をするものだったが、これは全く望みがなかった。なぜって pairwise coprime を判定するのに全組み合わせを考えると O(N^2) になるから。N の上限が 100 万だというのにそれは無理。5年前の自分ですらそんな馬鹿はやっていなかった (#19442249)。あらためて考えると、各素数について、それを因数とする A 数列の要素がいくつあるかを数えて、その最大値がいくつかを見れば良い。最大値が 0 なら A 数列はどの要素も素因数を持たない(すべて1)ということ。最大値が1なら、どのペアをとっても共通の素数を因数に持つことがないということなので pairwise coprime。最大値が N なら全要素に共通の素因数が存在するということなので not coprime。残る2以上 N 未満の場合が setwise coprime になる。提出 #73355090 (AC / 560 ms)。たしかに実装内容だけ見れば緑 diff だけど、書き方がひと通りでなく、他のどの書き方をしても Ruby では通らないということで、見た目以上の難易度になっていたと思う。■他の人の提出を見ると、素数列挙は require 'prime' でも良いらしい。pairwise coprime を判定するのに全組み合わせを考えるのではなくセグメント木のようなピラミッドを考えると Bignum を頼ることになりそうだけど log(N) ステップで判定ができて間に合うらしい。なんだ AC をとるのに色々やり方があるじゃないか。お前があほなだけやったか。だって今日初めてある1つの値が 0 から N の範囲のどこに位置しているかによって分類できるという問題の構造に気がついたわけなので、ぼけなのは間違いない。■■■E 問題。TLE だった最初の提出 #73314590 だけど、1行目の require 'prime'require 'faster_prime' に書き換えたものが余裕の AC だった (#73445802 / AC / 1361 ms)。これはくやしい。ABD の3完と、40 分残しての ABDE 4完でどれだけパフォーマンスが違っただろう。faster_prime ってなんぞ? と検索してみたら、mame さんの GitHub が出てきた (mame/faster_prime: A faster substitute for `lib/prime.rb`.)。これは信用できるなあ。gem install faster_prime したのでローカルでテストできるし積極的に使っていきたい。


2026年02月12日 (木) [AtCoder] バグ出しの最中である AWC beta。問題を解くにあたって一番問われているのが冗長な文章を素早く読み飛ばす日本語力かなと思った。その問題文。気にするほどではない些細な違和感がないではなかったけど、その中で3回目の「握手の列」の怪文章度合いが際立っていた。■「N 人の参加者が一列に、全員同じ方向(右向き)を向いて並んでおり」 右向きとやけに具体的に書かれているけど、前後左右どちらを向いているとしても同じことなので意味のない情報。さらに、これだけでは情景が想像できない。同じ向きを向いて横隊を作っているのか縦隊を作っているのかがわからない。だからその後の「全員が同じ方向を向いて一列に並んでいるため、隣り合う2人の参加者が握手をするとき、左側の参加者(番号が小さい方)の右手と、右側の参加者(番号が大きい方)の左手が触れ合います。」という論理がナンセンスに基づいている。むしろ2番目の文の前半部分はなかった方が、追加の情報から逆算して実際の並びはこうだったのだなと補完することができた。そして、ここで説明される行為を握手とは呼ばない。握手とは(直前までどちらを向いていようとも)向かい合ってするものだ。慣れていれば競プロ的な設定(隣り合った人が右手と左手をつなぐ。1番の人の左手と N 番の人の右手は余る)の肉付けに失敗したのねと了解できるけども、まじめな初心者ほど困惑するのでは? 世の中には文字とみれば先頭から末尾まで1文字ずつなめるようにしか読めない人間がいるのです。そういう人を指してまじめと表しました。■■■4日目の「バッテリー残量」についてはソースコードにコメントとして書いた。「与えられる時刻に単位がないが、放電速度は mAh/s で与えられている。s が second (秒) の略であるとしても、「時刻(無単位)」との換算をどう考えるか。すなわち以下で具体的な式が与えられているので解けるが、まったくすなわちではない。これは定義であり、すなわちより前には何もなく、今この式でこうと決めたのだ。」■ではどういう表現ができたか。単位時間という言葉が使われていたように思う。時間の1つ分。時刻が1つ進んだときの間隔。「単位時間当たり Bi mAh バッテリー残量が低下する」みたいな。具体的な時間の単位が時間なら1時間当たりだし、分なら1分当たりになるところが、単位を特定しない場合には単位時間当たりになるのではないか。子供のときはよくわからん表現だと思っていたが、他にはなかったのかなと今では納得できる。単位という言葉に内包されているからか1という数字は明示されていない(1単位時間当たりではなかった)。そのこともよくわからん原因のひとつだったと思う。単位という言葉にそこまで明確な輪郭がまだ与えられていなかったので(単が一だとかもまだ意識していない)。