/ 最近 .rdf 追記 設定 本棚

脳log[2026-02-23~]



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 の原因にしたことがある。


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単位時間当たりではなかった)。そのこともよくわからん原因のひとつだったと思う。単位という言葉にそこまで明確な輪郭がまだ与えられていなかったので(単が一だとかもまだ意識していない)。


2026年02月10日 (火) 二日前から突如としてお尻の穴の右内側面に固いでっぱりが存在していて、きゅっと締めるだけで異物感が主張するというのもあるし、単純にお尻を拭きにくいという不便もある。やや痛い。毎日物理的刺激にさらされる部位であり難しいような気もするけど、明日には消えてないかなあ。■あ、突然ではなかった。さらに二日前から固くなってる部分があるなと思っていたら、二日後にでっぱってきたのだった。押しても引っ込みませんよ。はあ、嫌だ (こんなこと日記に書きたくない)。


2026年02月09日 (月) 今朝は雪が残っていてとりあえず家の前だけ歩くつもりで自転車を押していったら、そのまま全行程1時間40分歩き続けることになった。自転車だとメーター計測30分(+メーター停止時間約10分)かかる距離で、だらだら歩くと2時間半弱かかるところだから、1.5 倍速で歩いた計算。さて……(片道が10km弱なのでそれぞれ順番に20km/h弱、4km/h、6km/h弱の想定です)。早々にジャケットを1枚脱いで腕まくりをして前腕をラジエーター代わりにしたが着いたときにはシャツが汗でくたくたになっていた。膝を持ち上げる筋肉なのかな、両鼠径部が筋肉痛ぽくて一日中動きがギクシャクしていた。


2026年02月08日 (日) [AtCoder] 今日は AtCoder Regular Contest 214。■A 問題 Same Sum Grid Path。分かれてすぐに合流する最少の4マスを考えると、あるマスの右と下が同じ数字でないといけないとわかる。4マス1単位をオーバーラップさせながら視野を広げると、スタートから等距離にあるマスが同じ値を持っていないといけないとわかる。そこまでやるならどのパスも同じ値を持つとわかる。実装ミスでペナルティを1回出しながら 18 分で AC。まあ 300 点問題なので (かなり遅い)。■B 問題 Missing Number in Graph。1からのパスを考えると、各頂点の番号と頂点1の番号との2つの値の XOR が N-1 個わかる。この N-1 個の値から頂点1の値がわかるだろうか。しばらくわからなくて N-1 個の XOR された値を眺めていた。それらの数字の中には N を超える値もある。たとえば N=4 だとして 3^4 = 7 なので頂点1の値が3か4ならそういうこともある。そういうのをヒントにして候補を絞りながら現実的な時間で頂点1の値を探索できるだろうか。N を超えてはみでたビットが M 種類あるなら 1<<M 通りの探索をして許されるだろうか。ダメっぽい。うーん。ここでちょっと飛躍をして、N-1 個の値全部の XOR を計算してみた。サンプルの3ケース目だから N=4 で、3つの値の XOR で、これは頂点1の値を含む4個の値の XOR と同じということになる。3個の値には頂点2と3と4の値と、奇数個の頂点1の値が含まれているから、そうなる。これと1から N までの N 個の値の XOR (0からの N+1 個の値の XOR でもいいけど同じこと)と XOR を取ると、食べられた数があぶり出されてくる。次は N が奇数の場合。サンプルの2ケース目がそうだけど N=1 でありあまり一般的なケースではない。同じ手法で N-1 個の値の XOR を計算したとき、偶数個の頂点1の値が相殺されて頂点1の値が消えてしまうから、あぶり出されてくるのは2つの値の XOR となり、そのどちらの値も頂点1の値として有効なので確定できない。-1 で良さそう? 他に確定する助けになる情報や方法はない? 投げたら AC だったので結果オーライ。■D 問題 Distinct Sum Grid Path。A 問題と同じ見た目。N<=13 だけど「全て 6000000 以下である」が難しい。電気毛布をオンにしたお布団があったかくて寝落ちしているあいだに終わっていました。今日は積もる勢いで一日中雪が降っていて帰り道が怖かった。信号で止まろうとしている車が黒い地面をひっかきながら 30 cm ほど滑って前の車にゆっくり迫っていくのが見えた。ノーマルタイヤのこの自転車ならどうなる。白い歩道がサクサク音を立てている。■自分のすべての提出コンテスト成績証。AB どちらも灰 diff で(ABC の diff と ARC の diff はそのまま比較できない印象)、茶パフォもありうるかと思ったけど、意外に昨日と同じような結果だった。つまり良くはない(「ぼちぼち」)。実際の diff は知らないけど、簡単な問題しか解けないのが自分です。


2026年02月07日 (土) [AtCoder] 今日は AtCoder Beginner Contest 444 があった。結果はまあぼちぼち。がんばって解いた E 問題が 2000 人くらいにもう解かれていたり。■A 問題 Repdigit。uniq.size でやろうとして String#squeeze メソッドの存在を思い出した。あんまり使い道がわからないメソッド。もう完成しているのに chomp を省いてマジックナンバーを1から2に書き換えたりしていた。■B 問題 Digit Sum。Ruby には digits.sum メソッドがあります。■C 問題 AtCoder Riko。問題文が難しい。あっとこーだーりこ? じゃがりことは似ても似つかなくてまったくわからない。謎の Riko に意識を持って行かれて問題が頭に入ってこない。さすがの 350 点だなとしばし考え込んでいた。全ペアを考えるには N が大きすぎる。ソートしてみようか。最大のものがまず L の候補。それより小さいものが L を作ろうとすると、半分に折り返して大きい方からと小さい方からでペアを作るしか方法がない。そうしてみると、最大のものが L ではない場合は、L の候補は最大と最小の和しかないということもわかってくる。答えの候補は2つしかない。ここで N=1 のケースがありうるか制約を確かめた。ある。最大と最小の和を求めるときに同じ1つの要素を参照するとおかしなことになりそうなので、場合分けをした。あと、答えの順序が昇順に指定されていた。提出直前に、ふと、どうでもいいよねと確認したら昇順と書いてあった。事前に要素数を出力させるのがありがちな罠。最大で2要素なのにソートした。■D 問題 Many Repunit Sum。変化量をメモしておいて、変化量の累積和を計算しながら各桁の値を求め、繰り上がり処理をしていく。しばし手が止まったのは、何桁まで処理すれば十分なのかを考えてのこと。N と A がすべて最大の 200000 のとき、繰り上がりの累積が全体で何桁桁数を増やすのか、考えてみてもわからなくて、事前に用意する配列の大きさが全く見積もれなかった。それで、普段は嫌ってやらないことだけど、配列の自動拡張に甘えてとりあえずやってみる方針で実装をした。出力できるサイズに収まることは確かなので TLE にはならないと思ったけど、提出後もまったく安心はできなかった。■E 問題 Sparse Range。問題を読む。空ではない全区間から選んで数える。一瞬勘違いしかけたけど、要素が1つしかない部分列が「どの 2 つの要素も差が D 以上である」という条件を満たすか否か。満たすんですね。あぶなかった。Array#all? メソッドと Array#any? メソッドでは初期値が異なっていて空配列に対して呼び出したときの結果が違うんですよという(論理的に正しい)ことを私は知っています。問題が理解できたところで、全連続部分列の累積和を列挙する的な処理がしたい。要素を左から見ていって、それまでの始点の累積に対して現在の要素が終点になる場合を考え、また、現在の要素を始点として累積に追加する。単一要素の部分列も対象だから、順番としては現在の要素を始点として追加してから現在の要素が終点となる場合を数える。何を記録しますか? 各要素ごとに有効な区間の右端が決まっている。右端をキーとしてそこまでの範囲を有効な区間とする始点の数を記録した。ところで、有効な区間の右端は区間に含まれるすべての要素によって制約される最小の値になります。現在の要素に照らして、期限を越えた区間を取り除き、長すぎる区間を切り詰めるように累積情報をメンテナンスすると、現在の要素を終点としうる区間の数が数えられる。これを BIT で数えたい。数えたいんだけど、現在の要素が有効な区間をどれだけ右まで伸ばせるかということがすぐにはわからなくて、BIT に区間を計上したり区間を切り詰めたりするための情報が足りなかった。結局それも BIT で予め求めることになった。BIT を使った2段構えでとてもたいへん。たぶんだけど問題を無駄に複雑にしていると思うんだよね。もっとすっきり解けたんじゃないかという気がする。使える頭がないので実装をがんばりました。■30 分残しても F 問題はさっぱり。順位表を見ると F と G を両方解いている人がとても少なく、F を飛ばして G を解いている人がそれなりにいる。今日の F は鬼門ですか? (難しいケースと面倒くさいケースが考えられます。その後わかったことは、G 問題と AI の親和性が高いケースも考えられます)■自分のすべての提出コンテスト成績証。4桁順位で水パフォ +21 レート。ぼちぼちなんだよなあ。■■■E 問題。尺取りというワードをよく見る。各始点ごとにどれだけ範囲を右に伸ばしていけるかということを、範囲内の値を SortedSet で管理しながら調べるらしい。値の範囲が大きすぎるので BIT でこれをやるには座圧が必要。偶然だけど自分の解法では可能な範囲を値ベースではなく添字ベースで管理していたので座圧なしで BIT に情報をのせることができていた。書いていたように別の解法はたしかにあったけど、そちらにはそちらの面倒が(SortedSet がない Ruby には)あったらしく、すっきりした解法はなかったのだった。


2026年02月04日 (水) [AtCoder] 先週末にあったらしいデンソークリエイトプログラミングコンテスト2026(ABC443)。都合の悪いことは見ないことでなかったことにできます。■A 問題 Append s。はい。■B 問題 Setsubun。とても難しい。N と K の上限がとても大きい(10 の 8 乗)のを見て全探索を諦めたけど、実は食べた豆の積算は2乗のオーダーで増えていくので何も問題がなかった。本番ではしかたなく 1 年目に N 個食べて、1+t 年目に N+t 個食べるなら、累計は (初項+末項)×項数÷2 だから……と考えていって、でも必要なのは 1+t 年後ではなく t 年後の累計だから t=t-1 を代入して……と補正して、サンプルの答えが1合わないから問題を読み直したら、0 年目に N 個食べるって書いてある! (初項+末項)の立式からやり直そうとして、実は出てきた答えを単にマイナス1するだけで補正できるなと気が付いて、修正に次ぐ修正でやっとの提出だった。7分かかった。■C 問題 Chokutter Addiction。シミュレートするだけ。3分半。■D 問題 Pawn Line。上に移動させるということは、入力された値(R_i)をマイナス1するということです。実装を終えてからサンプルが合わないことでこれに気がついて、どうやって書き直しをせずに修正するかを考えた。入力された R_i を N+1-R_i に変換するとその他の修正が不要だった。B 問題からこんなんばっか。提出したら TLE。処理内容は、高い山から順番に、左右にある低い山を1低い高さまで引き上げるという処理を繰り返す。山の高さの上限が N なのでプライオリティキューはいらない。全部の高さを処理対象にできる。各駒(山じゃなかった)が処理対象になるのは、初期の高さと、引き上げられた結果の高さの計2回であり、その処理では左右2つの高さを見るだけなので、O(N) であって TLE になる理由がわからなかった。TLE×2AC、差分は2バイト×2か所。実は最初に書いたときから、同じ駒が左右の駒から2回参照されてキューに2回登録されることがあるのは知っていた。左右の高さを参照するときに、現在の駒より低い位置にあるかを条件にしていて、現在の駒より2つ以上低い位置にあるかを条件にはしていなかったから。1低い位置にある隣の駒を1低い位置に移動する無駄な操作をキューに入れても害はないと思ってそのままにしていた。どういう入力でこのサボりが2乗のオーダーの計算に繋がるか。最初から操作の必要がない階段状の入力で1、2、3番目の駒が1、2、3回キューに入れられることで全体の処理量が (1+2+3+……+N) = N(N+1)/2 になる。■E 問題 Climbing Silver。BFS でも DFS でもいいからグリッドに結果を書き込んでいくことでグリッドの大きさ(最大で 900 万)に比例した計算量で答えが出せる。しかしとにかく壁破壊がやっかいだった。各列一番下の壁の位置を予め調べておいて、壁破壊ができる状況なら即座に最上段まで壁を破壊して結果を書き込んでしまえば良かった。6分オーバーで提出した #72910971 (WA×26) の間違いは、壁破壊が可能なのはスタート地点(N,C)から連続する左右の範囲に限られると勘違いしたこと。そうではない。壁を縫って到達した遠くの列の下半分が道ばかりだったら、そこでも壁破壊ができる。50 分近くあって時間内に実装しきれなかったうえに勘違いで WA とは何にも惜しくなくて逆に悔しくない。■■■精進。E 問題。提出 #72939980 (AC / 2313 ms)。完全に書き直したこれは行ごとの DP。マス目に4つの状態を持たせた。すなわち、「ゴール未達_道」「ゴール未達_壁」「ゴール到達」「ゴール到達_破壊」。初期状態で壁は ゴール未達_壁 となり、道は ゴール未達_道 となり、スタートマス (N,C) が ゴール到達_破壊 となる。あとは各行各マスで下の行の3マスを参照して、一番下にある壁の位置も{記録/参照}して、if 式が3重の複雑な状態遷移を書いた。Ruby で3桁 ms の爆速で通している人がいて (提出 #72911773)、ビット演算がその秘訣らしい。自分の複雑な遷移がビット演算にできるわけがないから、たぶん2種類の DP を平行してやるという噂の解法が、ビット演算に分解&合成するのに向いていたのかなと思う。あるいは全然別の解法なのかもしれないけど、一緒でも別でもどちらも知らない解法です。