/ 最近 .rdf 追記 設定 本棚

脳log[2025-01]



2025年01月03日 (金) ロマンシングサガ2リベンジオブザセブンをプレイしている。体験版をやったうえで購入しているので大いに楽しんでいるのだけど、納得いくまでいじった結果の設定が異端というか原理主義的というかそんな感じになった。■(1) ミニマップを消した。ミニマップがあると画面隅ばかり見て眼前の景色を見ず脳内マップができあがらず結果ミニマップを見続けるしかないということになるので、消した。タッチタイプを覚えるためと思ってキーボードに視線を落としたくなる誘惑と戦っていたときと状況は似ている。地形は勝手に覚わる。不便は最初だけ。そうはいっても、目的の方角を定めるためにミニじゃない全画面マップは開きます。それもしょっちゅう。でもたぶん最初だけ。■(2) 閃き予測アイコンを消した。戦闘中に、今この技を使うと派生技が閃きやすくなっていますよというのをお知らせしてくれるアイコン。消した。それが見えるとどうしてもその技を使いたくなりますよね? だけど状況に合わせてこちらが使いたい技、使うべき術というものがあって、閃きが最優先ではない。でも選びたくなりますよね? 消した。技をコンプリートするのはラスボス直前の時間潰しでいい。■(3) クエスト目標を消した。ミニマップの下に表示されるやつ。単純に画面がごちゃごちゃしてせせこましいから消した。そうはいってもクエスト目標が更新されたときの通知は表示しているし、プレイ間隔が開いて目的を見失うようなときはメニューを開いて確認すればいい。常に見えている必要はなかった。ちなみに、クエストターゲットはこちらですよと景色や扉に重ねて表示されるアイコン(黄色い◇)の消し方がわからなくて気が狂いそうだったのだけど、それはオプションではなくクエストの選択を解除すれば消える。だから新しく持ち上がったクエストを自動選択するオプションは当然オフにした。これが (4) つめ。■(5) 弱点表示をオフにした。敵の HP バーの近くに表示される、発見済みと未発見の弱点リストを消した。これも閃きアイコンと同じで、はてなマークが並んでいたら、弱点属性を明らかにしたくなりますよね? すでに弱点だと判明している技があるのに、それを選ばずに未知の属性を当ててみたくなりますよね? 図鑑を埋める目的はないのに行動が誘導されて、それは雑念であり迷いを生じるので見えないようにした。そうはいっても、技を敵にフォーカスしたときにこの技が弱点だよと教えてくれはするし、それはすさまじく親切で便利なことなので、弱点がどうでもいい気にしないということではない。一覧がいらないということ。状態異常効果のある技を当てたときに耐性があって効かないよと教えてくれるのもすばらしく親切で便利。そして耐性持ちが多すぎると知る。たぶん何が効かないかではなく何が効くかで弱点が設定されている。だから効くもの以外がすべて効かない。植物だから火に弱い、足があるから足払い(スタン)が効く、女性型だからカクテルに弱い……弱くない!■(6) 戦闘のタイムラインを消した。なんかね、戦闘のテンポが悪いなと思った。なんでか。視線があっちこっちへ飛んで忙しかった。画面左上のタイムライン。画面右下の残り HP、残り BP。画面左下の技リスト、技威力、消費 BP。現 BP と消費 BP が離れてるのが不便だと思うんですよ。技を選ぶときに2つを比較して BP の消費ペースを調節したいのに。パーティ情報として画面右下で HP と BP が一覧できることにもメリットがあるかなと考えてみたけど、別にそんなことはなかった。すくなくとも BP に関しては。HP が一覧できることはピンチを察知して回復につなげられるという点で大いに意味があるけど、BP が一覧できても回復したりはできないのだから。そこにあっても意味のない情報だよ。そんなんで右下左下左上と視線が忙しかった。どの敵をターゲットするかと画面中央も見なければいけない。閃き予測アイコンと敵の弱点属性リストはもう消したけど、ここからさらにタイムラインもいらないな、なくても困らないなと思ったので消した。そうはいっても敵が大技を構えているぞというお知らせが入るのだから、すさまじく親切ではある。これ以上の情報は溺れてしまうのでいらない。■こんな感じかな。オプションでこれだけいじれるあたりこんなのも想定内で、追加要素を押しつけないような気づかいがあったのかなと思う。■ダッシュオプションのキープの仕様に不満がある。これはボタンを押しているあいだだけダッシュするというオプションなのだけど、ボタンを押し続けていても一度スティックを離して止まるとダッシュを再開しない。トリガーという設定もあって、これはダッシュボタンを一度押すと以降立ち止まるまで走り続けるというオプション。混ぜないで欲しい。頭の中にモードを保持したりボタンに2つの意味を持たせたりしたくないからキープを選んでいるのであって、ダッシュボタンの状態とダッシュ状態が連動しないのは受け入れられない。オートという設定もある。オートを選ばない理由は、走り始めるまでの時間がかったるいからだ。地図を開いたりメニューを開いたり曲がり角で敵影を伺ったりと立ち止まる機会は多い。そのたびに走り始めるまでの歩き時間が生じる。また、待ちたくないがために立ち止まってはいけないというような圧を感じるのも大嫌いなので避けたかった。トグルという設定もある。トグルを選ばない理由は、とっさにダッシュを止めるときに操作に迷いが生じるからだ。さっき書いたモードと意味の二重性から反応が遅れる。■陣形を乱される条件がよくわからない。ダッシュ中に接触したら乱されるのはわかる。というかそれしか想定していない。敵に正面を向けて待ち構えていたのに乱されることがあるのが納得いかない。(追記) ダッシュしてても必ず乱れるわけではないんだよな。背後から接触されると必ずかな。横から接触されてあっと思っても乱れないこともある。ファジーなのは一番つまらんぞ。■BP の消費ペースを調節したいと書いたけど、術酒や霊酒は見かけたら買い占めるしわりと使っちゃう。敵ドロップで BP が現地調達できるときは作戦をがんがんいこうぜにするチャンスだ。


2025年01月11日 (土) [AtCoder] 今日は HHKBプログラミングコンテスト2025 (ABC388) があった。では A から E まで。■A 問題 ?UPC。入力の1文字目だけ使います。■B 問題 Heavy Snake。ヘビの文字を見ると忌まわしい記憶がよみがえってくる(Snake Numbers。C 問題で、水 diff!)。これは簡単。愚直に判定して許される制約。■C 問題 Various Kagamimochi。解釈に迷って問題文を注意深く読んだ。種類数を聞かれているのだけど、これはありうるすべての組み合わせ方を聞かれている。同じおもちを使う異なる組み合わせも数える。二分探索でもいいけど、予めソートされているので尺取りだと線形時間になる。ちなみに同時にいくつの鏡餅が作れるかは E 問題で問われていた。■D 問題 Coming of Age Celebration。最初の提出 #61559311 が TLE でびっくりした。どこで時間を使っているのかわからないし、削れる部分も見当たらない。そうすると入力が大きすぎることを疑うのだけど、Ruby スクリプトのレベルでその対策は行えない。結局 E 問題を通したあとで C++ で書き直したのだけど、それは 579 ms かかっている。これをざっくり数倍すれば TLE なのだから Ruby で通らないのは当たり前に思えるのだけど、実は Ruby で通している人がごろごろいる。Ruby による D 問題へのすべての提出。見比べて何が違うのかわからない。入力の受け取り方が $<.readgets かの違いか? ローカルでも遅いから再現性があるんだけど、何が悪いのかさっぱり。提出 #61608160 (AC / 256 ms)。配列の shift をやめて添字アクセスにしたら数十秒が数百ミリ秒になって AC になった。S という配列に対して shift したり []= で代入したりするのがどういうわけか遅くなるみたい。それが [] と []= の組み合わせだと大丈夫だと。これが S という配列に対してイテレータでループを回している最中の話だと因果が見えやすいけど、そうではない。この時間の差は Ruby 3.1、2.7、1.9、1.8 までさかのぼっても変わらなかったので、Ruby で最初の提出のような書き方をしてはいけないということを自分が知らなかっただけということになるのだけど、何度見てもまずさがわからないのがやばいと思う。一応書いておくと、Ruby の Array#shift は要素を前に詰める線形時間の操作ではないし、shift 操作が(配列の実データ共有を無効化する) copy on write を引き起こすこともない。……と書いて気がついたけど、[]= による代入が配列のコピー書き換えを引き起こしているのだな。自分には S という配列が1つあるだけにしか見えないから、書き換え前にコピーしなければいけない理由がわからないけど。shift には注意しよう。あ、問題について書いていない。各人が配る石がどのタイミングで尽きるかをメモしておいて、あとは決まった流れを再生する。■E 問題 Simultaneous Kagamimochi。上に乗せるおもちは小さい方から順番に選んでいくしかない。最初に間違えたのは、一度下にしたおもちを上に乗せるおもちに再利用してしまったこと。それで乗せ替えをしたりややこしいことをしてなんとか答えを合わせたけど、おもちを前半と後半に分けるともっとすっきり解けたのだろうか。■F 問題 Dangerous Sugoroku。黒マスブロックの前後に集中する BFS なのかなと思ったけど、いい具合に集中する手順が出て来なかった。■G 問題 Simultaneous Kagamimochi 2。セグメント木で連結を工夫して二分探索でできないかな。■E まで解いてまさかの緑パフォ。あまりにも厳しい。■■■精進。G 問題。セグメント木でどのセグメントをどのように連結して答えに近づいていくかを考えていたら、それってダブリングぽいなと思った。提出 #61669596 (AC / 503 Byte / 1728 ms)。セグメント木ではなくダブリング。たぶんメモリ使用量の点で、ざっくり要素数の2倍を使うセグメント木に対して、ダブリングのために要素数×log2(要素数)のサイズのデータを準備したのが不利だと思う。しかし 2 対 18 は定数倍の範囲。できあがったものは実装途中よりもシンプルになったけどすんごくややこしくて、バグはなかったけど寝る時間がなくなった。実はやってることは E 問題への提出 #61589354 とあまり変わらなくて、高速に乗せ替えをするためにセグメントごとに前計算をしたみたいな感じ。セグメントの連結というのが上のおもちと下のおもちがオーバーラップしないように乗せ替える操作にあたる。乗せ替えると何が起こるかというと、前計算で得ていた下に敷くおもちのインデックスが右にずれる。どれだけずれるかは添字との差だけから計算できる。E 問題を解くのにそんな回りくどいやり方をして時間を無駄にしていたのだった。ダブリングでなくセグメント木で解こうとすると、何をリクエストして何を得るかという検索インタフェイスがどうあるべきかがよくわからない(だから都合良くダブリングを採用した)。二分探索をセグメント木の外部に担わせると木の操作の log と合わせて log が2乗になってしまうけど、log は1つで済ませられるはずなので(実際そうだった)、セグメント木に探索を丸投げするために何をリクエストすればいいのか。汎用性(普遍性)のある問いとは何か。■セグメント木に乗せるのは下に敷くおもちのインデックスそのものではなくて、いくつ右かというオフセットにするのがいいらしい? そうすると l+k+max(l...l+k)≦r で判定できる? k を二分探索すると log が2乗になるので Ruby が許されるかどうか。提出 #61683769 (TLE×13/AC×33)。許されなかった。残念。もう AC があるので定数倍改善の意欲はありません。しかし、インデックスの代わりにオフセットを扱うだけでびっくりするほど簡単にセグメント木が利用できるようになるのだね。そういううまいやり方があるのは ABC371-F「Takahashi in Narrow Road」(20240914) のおかげで知っていたはずだけど。「FはまずXi←Xi-iとすることで条件を狭義単調増加から広義単調増加に書き換えておく。すると用事を完了するためには邪魔になる人もろとも目的の座標までずらせばよく、」(週記(2024/09/09-2024/09/15) - kotatsugameの日記)。他には ABC353-G「Merchant Takahashi」(20240511) も同じようなセグメント木の使い方をする。セグメント木ではないけど ARC120-C「Swaps 2」(20211022p01) も同じ発想で解く。以前はポテンシャルという勝手用語で説明していたけど、改めて共通点を探してみると、絶対相対変換という見かたができると思った。位置相対的な値をセグメント木に乗せても共通の土俵で比較することができなくて困るときは絶対的な値を乗せる。そしてややこしいことに逆のニーズもあって、今回の F がそうなんだけど、絶対座標が扱いにくくて相対値を乗せたいこともある。そういうテクニック。■ついに許された! 提出 #61689758 (AC / 1030 Byte / 1837 ms)。セグメント木。定数倍ではなくオーダーを改善して log を1つにした。懸案だった検索インタフェイスは左側の境界を与えて判定関数が true を返す区間の右端を探るメソッドということにした。しかし 118 ms オーバーで惜しくも TLE (#61689533)。しかたがないので判定関数ではなく判定の閾値を引数にして判定処理を埋め込む苦肉の策でやっとの AC。苦しい。


2025年01月19日 (日) [AtCoder] 精進。昨日あった ABC389-F「Rated Range」。これまで何度もこの日記にお風呂で考えてきたと書いてきたけど、とうとうお風呂に入る必要がなくなってしまった。服を脱いで入ろうとしているときにひらめいたんだけど、ある範囲のレートを1増やす操作を何度行っても、レートの序列が入れ替わることはないんだよね。操作の前後でソートされた状態が維持されている。q 番目のクエリの初期レート x が i 番目の大きさだったとして、値がある範囲である区間に1加算する操作を繰り返したあとでも、i 番目の位置にクエリ q の答えがある。提出 #61874909 (AC / 1265 Byte / 1075 ms)。最初の実装に 10 分、貼り付けた自分の BIT の使い方を間違えていてデバッグに 15 分ほど。だけど問題を十分に理解して解法を導くまでにひと晩寝る必要があった(布団の中で考えようとしたらそのときまで解こうとしていた問題を覚えてなくてそのまま寝た)。F 問題の精進でけりがついたので A から E までについても書く。どこまでがふりかえりでどこからが精進でしょうか。喜んで書く気にはならない不本意な出来であるのは間違いない。■A 問題 9x9。スクリプトなのを利用して eval で。■B 問題 tcaF。Fact のリバースだということがわかるまでしばらく問題名を眺めていた。意味までは考えなかったけど今あらためて考えてみると、一般的に下りで定義される階乗を上り階段で計算するような解答になることを反映していたのだった。■C 問題 Snake Queue。累積和を伸縮すれば解けるんだけど、数字を合わせるのにかなり手こずった。なぜか。長さで定義されるヘビであるけれど、i 番目のヘビの長さは i 番目のヘビの頭の位置に寄与しない。このずれがわかっていてもややこしかった。■D 問題 Squares in Circle。結論を書くと、0.5×0.5 の正方形を単位として、ある x における原点を中心とする半径 R の円の Y 座標を求めれば、1×1 の正方形の数も数えられる。第1象限についてだけ考えて2倍したり4倍したりすれば良い。ただし X 軸 Y 軸に重なっている正方形だけは分けて考えなければいけない。ふりかえれば別に難しい計算ではないのだけど、このやり方でできるとわからなかったし、見通しが利かないなかで正しい式を見つけ出すまでにはそれなりの時間と試行錯誤が必要だった。■E 問題 Square Price。最初に提出したプライオリティキュー解が TLE だった。制約を見たら M の上限が 10 の 18 乗だった。キューから M 回取り出そうとしたら TLE になるのは当たり前。どうするか。ある程度の操作をまとめたい。二分探索でボーダーラインを決め打って、+1 個のコストがボーダーを超えない範囲で各商品を買う。その合計金額が M 円を超えない範囲を探る。ボーダーと合計金額に直接的な関係はないけども、連動していることでしょう。ここからが長かった。ボーダーラインから個数を求めるのに二分探索をしたら外の二分探索とあわせて log が2乗になって TLE だったから、式をこねくりこねくりして、いつまでもいつまでもこねこねしていた。この提出 #61841606 の6行目の式(k = (b/p+1)/2)がまったく一筋縄ではいかなかった。他にもね、14 行目と 15 行目にある2つの式 k*k*p(k+k+1)*p が似てるでしょ。自分の目には同じに見える。取り違えてもしかたないよね。それから、後半7行でやっているボーダーライン上のアイテムを買えるだけ買う処理だけど、これ単純に割り算で計算できるらしい。二分探索で求めたボーダーラインの意味を考えればその通りなんだけど、半信半疑になってしまうところがあると思う。■F 問題まで解ける問題が並んでいて、だけど時間内に解けたのは C 問題までってどういうことですか。最近の問題傾向のせいにしてもいいですか。自分は数字とか式を精密に扱うのはまったく苦手なので、たこ焼きに関する問題が解きたいです。文章で発想のヒントとなる過剰なディテールが与えられてるといいなあ。そして発想だけで解けるといいなあ。式変形とかまじ無理なんで、D と E が解けなかったのもそれが原因なので。■D 問題の早い人の提出を見てると、ループで1つの式の合計を求めて、4倍して1を足して答えにしていた (#61802287)。どういう見かたをすればそんなシンプルな理解に至れるのだろう。■F 問題に関連してセグメント木の max_right メソッドへの言及をいくつか見た。どうやらそれは前回の ABC388-F に関して自分が「セグメント木で解こうとすると、何をリクエストして何を得るかという検索インタフェイスがどうあるべきかがよくわからない」「懸案だった検索インタフェイスは左側の境界を与えて判定関数が true を返す区間の右端を探るメソッドということにした」(20250111) と書いていたメソッドそのものではないかという気がする。お名前いただきました。■E 問題。「制約を見たら M の上限が 10 の 18 乗だった。キューから M 回取り出そうとしたら TLE になるのは当たり前」とさっき書いた。AC までいった今だからわかるけど、キューから取り出す回数の上限は M 回ではない。(k+1)^2-k^2 = 2k+1 であることから、+1 個のコストは個数に比例して上がっていき、その和は2乗のオーダーになるから(Σk = n(n+1)/2)、取り出す回数は M の平方根である 10 の9乗に比例する。ていうかコストの定義が kkPi なのだからそれはそう。それでもやっぱり TLE になるように M の上限が 10 の 18 乗程度に定められている。■E 問題。ボーダーラインを求めてさらにボーダー上の境界に注目する問題としては PAST8-I「/2 and *3」を思い出す (#26574800)。知ってる問題だったんだよ。解法の枠組みが自明で、でも式変形が難しすぎた。


2025年01月25日 (土) [AtCoder] F 問題までけりがついたので今日あった ABC390 について。今回も前回と同じく F まで解けない問題ではないけど、すっごく時間がかかる。A 問題から5分かかったし。■A 問題 12435。1回転倒を直してみて 1,2,3,4,5 になるかどうか。最初からソート済みの場合が No であることに注意。■B 問題 Geometric Sequence。解答を書いてからサンプルを試してサンプルの3でひっくりかえった。公比 0.8 の等比数列ですって。3項で分数で等式を作って通分すればいいのかもしれないけど、そこは Ruby なので Rational におまかせ。■C 問題 Paint to make a rectangle。黒のマスを囲む上下左右の大枠を求めたら、その内部がすべて黒か?であるか。■D 問題 Stone XOR。N が 12 以下だけど、12 の階乗が 4.7 億 (470 メガ) を超えるので愚直 DFS は通らない。少なくとも Ruby では望みがない。愚直 DFS を書いて1分以上かかるのを確認してからどうやって処理量が減らせるか考えた。1の袋を2の袋に足してから2の袋を3の袋に足した場合と、1の袋を3の袋に足してから2の袋を3の袋に足した場合は区別する必要がない。どうやって同じことの繰り返しが防げるか。すでに混ぜ物がされている袋は他の袋に混ぜる必要がないのではないかと考えた。■E 問題 Vitamin Balance。ビタミンごとに3回処理をして、カロリーから摂取量への換算表を作る。摂取量で二分探索をして答えを求める。答えの二分探索の中で換算表を二分探索で逆引きすると TLE (と WA と RE) が出たので、ありうる摂取量のリストを作ってからどの摂取量が答えになるかを調べた。これだと支配的な要素はソートの O(NlogN) になる。■F 問題 Double Sum 3。間違った問題を解いていた時間がほとんどといっていいほど長かった。問題文中の大文字の L,R は数列の区間を表す数字だけど、小文字の l,r は数列の値の範囲を表す数字。自分は x 座標が上下で y 座標が左右を表していてもそんなのは便宜的な区別だからどうでもよくて、第1軸第2軸以上の意味を勝手に持たせて直感や慣例に反すると文句を垂れるつもりはないつもりでいたけど、大文字小文字が異なるだけで同じアルファベットに異なる意味を持たせるのは罠だと文句を言いたい。そういう誤読も含めて試行錯誤したことの結論だけ書く。小さい値から順に処理をして、自身が連続した値グループ(f 関数の内部で l,r で表される範囲)の中で最小の値である場合に限って、主客転倒で L,R の選び方を数えて操作回数を計上する。自身が値グループの中で最小の値であるとは、左右にある同値と -1 した値のどちらでも最も近くにあるものを含まず、自身を含む区間が選ばれた場合に、そのようなグループが発生する。l,i,r の3つの値を使って (i-l)*(r-i) の簡単な式で数えられる。■自分のすべての提出。宿題が多すぎるんよ。D から精進でした。いつまで水色かわからんで。


2025年01月26日 (日) [AtCoder] 今日は ARC191 があった。配点が 4-5-6-7-8 であるように、下位の方(Div.2)。ABC で ABC の3完を繰り返しているにもかかわらず幸いなことにまだ Rated 参加権を失っていなかったので、時間通りに参加した。■A 問題 Replace Digits。S の先頭から T の大きい数字から上書きしていけばいいんだけど、T の最後の文字がちょっと困る。最後の文字でなければ、例えば T が最後でない位置に 1 を含んでいたとしても、T 自身の他の数字で上書きした体(てい)で 1 の数字をなかったことにできるけど、最後の文字だけはその手が使えない。他の人の提出(#62128560)を見ると、すごく簡単そうに最後で s[-1]=tt if !s.include?(tt) と帳尻を合わせている。自分はすごーく苦労して間違いながら回りくどい処理をした。提出 #62132900 (AC)。最後の文字を最初に取り分けてメインの上書き処理を通さなかったのがうまくなかった。あとから最後の文字だけ上書き処理をして、それによって余ったすでに上書きに使われていた T の文字が無駄にならないように玉突きで再利用を繰り返した。玉突きの適切なインデックスを求める 19 から 21 行目と 28 行目の find メソッドの条件がまあ間違いやすくて WA を2つ出した。N=M=5 程度の小さなランダムケースを作成して、スクリプトの解答と自分の解答(私はバイオコンピュータを内蔵しています)を突き合わせて NG ケースを探して見つけた。でもこの苦労は避けられたはずの無用な苦労だったと。■B 問題 XOR = MOD。A とほぼ同じ人数が通しているみたいだけど自分はこちらの方が解きやすかった(A 問題通されすぎ)。N を増やしながら愚直解を列挙してみれば、N=X が必ず最小の解として存在している。また、解の上限は 2N-1 らしい。N が2の冪乗のときにもっとも解が多く、区間内のすべてが解になる。そこを手がかりに前後の N の2進表現を考えてみると、0の数が答えの数(2.pow(0の数))を決めている。つまり、N の0だった桁が0か1に変化したものが X (決めつけ)。提出 #62134372 (AC)。K-1 のビットパターンを N の0のビットに埋め込む。■C 問題 A^n - 1。N+1 が素数だと解きやすい気がするんだけど、それだけ。こういう問題にアプローチする術(すべ)を持っていない。■D 問題 Moving Pieces on Graph。一応読んだだけ。基本的には最短経路+1本の辺があればコスト2を払って一方が待避することですれ違いができる。最短経路が部分的にでも2本に分岐していれば追加コストはいらない。もちろん全く共有辺を持たない最短経路が2本あるのでもいい。最短経路でなくても、+1 コストの経路には価値があるし、待避できる余分な辺がないならどんなコストであっても2番目の経路に価値がある(全体が輪っかのグラフを想像する)。どうやってコードにするかはわからない。コーディングだけが問題かもわからない。■D 問題。すごいケースがある。S と T が直線で通じていてそれ以外の迂回路がないとき、S または T から外部へ双方が待避して位置を入れ替えることができる。それはもう最短経路とか全く関係がない。■A、B がどちらも緑 diff だったらしい。ARC は怖いところだよ。緑落ち寸前の自分が解いているという事実に納得しかないけども。■■■D 問題に訪れた AtCoder 最高の瞬間。提出 #62153446 (WA×1/AC×63)。circle_like というケース名をヒントにランダムケースに傾向を与えてダメケースを探した。提出 #62154569 (AC)。補助なし時間制限ありでこんな問題解けるわけないよ(自分には)。正解を出力する他の人の AC プログラムを助けにしてデバッグに次ぐデバッグで数え切れないバグを潰してやっとこれ。■正解を知るのにこちらの提出 #62136607 をコンパイル(&リンク)したものを使わせてもらっていたのだけど、ソースを読むと、変数 L と R を使ってささっと2つ目の最短経路を見つけている。どういうことか。それぞれ f(G,S) と f(G,T) に対応していることから S と T から BFS した結果かと思うのだけど(f 関数を読まない)、最短経路上にある各頂点について、一方(とりあえず S)からの距離をメモして、その距離に重複があれば迂回路があると判定できる? 迂回路があるということは、S(または T) から等距離に異なる2つ以上の(最短経路を構成する)頂点が存在すること? そうっぽいけどこれ当たり前にわかること?■自分がやったこと。S から BFS をしたあと T から後戻りすることで最短経路を1つ特定する。最短経路上の S を除く各頂点について、隣接頂点のうち最短経路にないものの S からの距離を調べる。自身の距離を d として、d-2 以下であることはありえない。d-1 である場合は、異なる最短経路が合流してきたことがわかる。d である場合は +1 コストの経路が合流してきている。d+1 の場合は、ここから分岐したのかもしれないし、+2 コストの経路が合流してきているのかもしれないけど、どちらの場合でも扱いは同じ。引き返してはいけないというルールがないので、分岐してすぐ戻ってくることで +2 コストの経路になる。S と T には特別な扱いが必要。S には合流してくる経路がなく分岐していく経路しかないので調べない(今は分岐路の合流点を調べている)。T に隣接する頂点で d+1 の距離を持つ頂点に注意が必要。さっき引き返してはいけないルールがないと書いたけど、T に限っては引き返す経路がすれ違いのための迂回路にならない。しかし +2 コストの本当の迂回路が合流してきている場合も考えられる。最初にやった S からの BFS を T で止めることでこの2つを区別できるようにした。これには +3 コスト以上の迂回路の合流を妨げない意味もある。あとは「すごいケース」への対応を追加でやる。WA×1 はこのケースへの対応がバグっていたせい。最初の1回の BFS 結果を流用するのをやめて、2回目3回目の BFS をすることで間違いがなくなった。たいへんすぎるよ。まずやるべきことがわからないし、やるべきことをやる方法がわからないし、正しくやるのも難しい。■■■『はじめての数論 原著第3版』を開いている。第21章は「法 p でのべき乗と原始根」というタイトル。C 問題は位数と原始根が前提知識として必要だったとわかる。そしてもちろんそれを知っているというだけで解けるなら問題にならない。


2025年01月31日 (金) どこか経由で読んだ。「私の観測範囲の C の初学者、構造体で詰まる人が結構いる。でもってポインタは案外詰まらない。」■構造体で詰まるという詰まり方に興味がある。ポインタでは詰まらないという点に関連付けて想像してみる。C の前に他の Python みたいな言語になじみがあると、数値など不変型とオブジェクトなどの参照型はすでに知っているものと思う。ポインタは参照になぞらえて理解できる。構造体はオブジェクトになぞらえて理解できそう? C にしかなくて戸惑うのは、不変ではなく参照でもないもの、malloc せずに存在している構造体ではないだろうか。これは自分の実感に基づいた想像で、Ruby に散々なじんだあとで C++ を触ると、変数のごつさにびびってしまう。スライシングみたいな罠にもなるやつ。詰まり方に興味があるというのは要するに、構造体を malloc して使うのは普通にできるんじゃないかと疑っている。