/ 最近 .rdf 追記 設定 本棚

脳log[2024-12-24~]



2024年12月24日 (火) [AtCoder] 精進……失敗! 先週末あった ABC385-F「Visible Buildings」。傾きでソートしながらどんどん更新していくような解法を検討していたのだけど、全然違った。「Fはまず何も考えずに二分探索を書いた」という人がいるが、さっぱりわからない。別の所で「原点から全てのビルを見られなければ、左から順に左隣のビルの陰にならないように高さを上げていきます」と読んで、嘘だぁと思いながら、なんで左隣のビルを見るだけでいいのかを考えていた。こんな感じ。3つのビルがあって原点に近い方から A、B、C とする。AB のてっぺんを繋いだ直線を C まで伸ばしたときの上下を考える。C の上空を通り過ぎるとき、答えに近いのは BC のてっぺんを繋いだ直線なので A を起点として考えるのはおしまい。C の側面に触れるとき、AB を結ぶ直線を保留にしたまま B を起点にした直線について考える。いずれにしろ A と C が関係を持つことはない。A と C を結ぶ直線が A と B を結ぶ直線よりも答えに近いときは、B と C を結ぶ直線の方がより答えに近いのよね。だから A と C の関係は答えに寄与しない。本当に? わかりません。実装を始めたらサンプル2と3の違いが難解すぎて手が止まった。共有点を持つとき、見えないんだってね。AC のてっぺんを結ぶ線に B のてっぺんが触れるとき、A から C が見えない。提出 #61050894 (WA×1 / 320 Byte / 1329 ms)。1ケースだけ通らなかった。誤差が大変というのを見かけていたので答えを出力するとき以外全部整数で計算したけど、1ケースだけ合わない。どうしたらいいのかもうわかりません。■A 問題 Equally。全部同値か、どれか1つの2倍が3数の和か。■B 問題 Santa Claus 1。シミュレート。各家1回ずつしか数えないので @ を通過したあと . に書き換えた。■C 問題 Illuminate Buildings。難しかった。実装で2つ間違えてペナルティは4回出した。AC が出たのは終了5分前。2乗が通る制約だからと愚直に書いて、念のために最大ケースでテストしたら TLE になりそうだった。愚直というのは始点を固定して全ての間隔を試すというもの。よく考えると右側にある同じ要素を何度も参照するから2乗では済んでいない。そこで間隔を中心に考えることにした。1つおき、2つおき……の各数列について、同じ要素が最長でどれだけ続くかを数える。間隔が S なら長さが N/S 程度になる S 本の数列を考える。間隔の選び方がおよそ N 通りだからこれで O(N^2) になる。ここでも罠があって Array#values_atEnumerable#chunkInteger#step を組み合わせた解答が予想よりも時間を食っていた。Enumerable#each_cons には大きい数を引数にしたとき尺取りの計算量 O(N) では済まないらしい罠があると思ってるんだけど、ここにもあったのだろうか。手続き的に書き直して最初に提出するまでに 15 分かけた。そこからペナルティを重ねるんだけど、最後まで見つけられなかったバグは N=1 のケース。間隔に注目したせいで単一要素のケースが漏れて nil を出力していた。■D 問題 Santa Claus 2。どうやって計算量に対処するか悩む。たとえば BIT を使えば各行、各列のどこに家を置いて、どこから家を取り除くかは自在に(対数時間で)できる。あるいは行ごと列ごとに移動区間と家の並びのソート列があれば並行してスキャンしていくことができる。どちらも行データと列データに重複して登録される家を二重にカウントしないために同期が必要。これは行に基づいて得た訪問家リストと列に基づいて得た訪問家リストを最後に線形時間でマージして出力すれば良い。ということを考えてから必要なデータ(行ごと列ごとの移動区間)を集めて整理していった。そうすると家を中心にして考えたとき、行データと列データを参照して二分探索をするとその家が訪問されるかどうかがすぐに判断できるなと気がついて、後半の実装がちょっとだけ楽になった。BIT はいらないし、ソート列の並行スキャンもいらないし、答えのマージもいらない。ランタイムエラーでペナルティを1回出したのは N×N のグリッドを想定していたせい。D の提出をするときに C が WA になっているのに気がついて、C のデバッグをしているときに D が RE になって、C のデバッグを優先したけど結果的にデバッグしやすかったのは D だった。いっときは C をあきらめて E 問題を読んだほど。■E 問題 Snowflake Tree。木 DP かなと思って実装を始めたら親方向の情報が欲しくなって全方位木 DP だと気がついて、残り 10 分での実装をあきらめて C のデバッグに戻った。C は終了5分前に、E は終了 10 分後に AC。最も簡単なタイプの全方位木 DP だと思ったけど、もっと簡単に中心を全探索して間に合う計算量だったらしい。頂点数が N でそこから辿る辺の数が両方向で 2×(N-1) だから間に合う。しかし気付けない。だって解けるんだから。それで時間が足りてればね。■C のミスと D の重さにやられて E を通す時間がなかったのが悔やまれる。F はどれだけ時間があっても無理なので期待も諦めもない。


2024年12月22日 (日) [COSMOS] メモリ 2GB×2 を抜いて 8GB×2 を差した。4GB×2 と合わせて 24GB になった。ところで、このメモリって DDR3 なんです。1枚 1300 円だったけど、いつまで手に入るかがもうあやしい。DDR5 が差せるマザーボードを選びたいけど、載せたい OS がない。


2024年12月18日 (水) [AtCoder] 精進。ABC357-F「Two Sequence Queries」。20241201 で初めて実装した区間更新ができるセグメント木のテストを兼ねて挑戦していた。提出 #60878023 (AC / 2167 Byte / 3561 ms)。TLE を回避する高速化にあたっては先達の提出(#54387396#54497837)を大いに参考にした。最も重要なアイディアは Array ではなくクラスを使うことによる自己書き換えだと思った。これによりオブジェクトの使い捨てが抑制できる。1点更新のセグメント木で凝ったマージをしようとするとすぐに TLE になるのもおそらく原因は同じで、1セグメントあたり配列に3要素も4要素も値を保持し、更新のたびに新しい配列を作成するコストが重すぎるのだろう。具体的な数字やどこで読んだかは忘れたけど、配列のサイズが4つや5つを超えると要素を Array オブジェクト(を表す内部データ)に埋め込む最適化もできなくなるだろうし。■それほど重要ではないけど TLE と AC を分ける細かい選択がいくつもある。hmmnrst さんの複数の提出の差分を調べると、mod の値はインスタンス変数に保持するより定数に保持する方がいいみたい。多重代入は1行ずつ分けるのがいいみたい。多重代入が重いのは知ってるし、仕様の変更でさらにちょっと重くなるらしいのも知ってるけど、冗長なのを嫌って自分は多用するんだよね。だけど多重代入が TLEAC を分けているのを実際に見ると、好き嫌いではなく選択の余地はないのだなと理解してしまう。多重代入を分解するときは代入前の値を参照しているつもりで代入後の値を参照するバグを仕込みやすいので注意が必要。過去に何度も苦しめられたし、今回も、自分の AC 提出の 93 行目、Seg#apply メソッドで @ab 変数への代入順がイレギュラーなのは、最初からそうだったわけではなく、@a、@b 変数への代入のあとでは値が狂ってしまうというバグとデバッグの結果そうなっている。同じメソッドのことだけど、2つのアクセサを3回ずつ呼び出して値を参照していたのを、1回ずつに減らすためにローカル変数に受け取っている。プロファイラ(ruby-prof)で呼び出し回数と消費時間が上に上がって来ていたから対策した。自分のスクリプトの Seg クラスと Op クラスは扱いから考えて Struct にしたかったのだけど、数百 ms 以上遅くなるみたいだったのでクラスにしている。Seg#concat メソッドの呼び出しはレシーバと第一引数を同じにすることで容易に Seg#from メソッドで置き換えられるのだけど、これもパフォーマンスの劣化が無視できなかったのでスクリプトの冗長さをあえて受け入れている。Seg#from メソッドは引数で自分を完全に上書きするあたりコンストラクタと同じなのでインスタンスではなくクラスに生やしたいメソッドなのだけど、パフォーマンスのために自己書き換えが目的なのでしかたなくインスタンスメソッドにしている。ST#set メソッドと ST#get メソッドは8割が共通なのでマージできなくはないけど、わずかに遅くなるのとそうすべきなのかがわからないので分かれたままにしている。%998244353 をどこに置いてどこに置かないかも制約から計算してよくよく考えた結果のこと。実は自分のスクリプトは1秒以上も差をつけられて遅い状態が1日以上続いていたのだけど、この要不要の見積もりを誤っていたことが原因だった。パフォーマンス特性がこんなにも違うのだから、Bignum を Integer の背後に隠すのはどうかと思うんですよ。理想と現実にギャップがあるとき、現実を隠蔽することに利があるとは思わない(自動的な昇格ではなくクラスについて書いている。デバッグがしにくい)。他にも子要素の添字を計算する際の +1 を省くために内部データを 1-indexed にしたりという、針の穴を通すような細かな積み重ね抜きでは Ruby で AC を取ることができない。正直言ってコンテスト本番ではこの手の問題(遅延セグメント木、N>300 のワーシャルフロイド法、N=5000 の2乗の DP など)はさっさと投げ捨てて他の問題を解いた方が良い。なお、できる人は Ruby を投げ捨てるもよう。■記事を閲覧履歴から発掘した。「Ruby 1.9 では RVALUE に「embed」という考え方が導入され、文字列や配列などデータのうち、サイズの小さいモノは別途 malloc するのではなく RVALUE の中に埋め込んでしまうことで、 malloc & free のオーバーヘッドを削減でき、またキャッシュの局所性を高めることができます。」「ちなみに Array なら 3 つまで embed で扱います。」(Ruby は String をメモリ上でどのように扱っているのか? | IIJ Engineers Blog)■最初期の提出を見てみると、出力用の第3引数を渡すことで配列を使っていてもオブジェクトの使い捨ては抑制できていたみたい。それでひどい TLE なのだから、クラス化による最大のメリットは [] メソッドを使わないインスタンス変数へのアクセスなのかもね。


2024年12月14日 (土) [AtCoder] 今日はトヨタ自動車プログラミングコンテスト2024#12(ABC384)があった。まずまずのでき。ABCDE のふりかえりと F の精進を。■A 問題 aaaadaa。言われた通りに。正規表現を使った置換だと一発だったのかな。操作が否定で定義されていて結局何をするのかよくわからなかったので言われた通りに。■B 問題 ARC Division。言われた通りにシミュレート。■C 問題 Perfect Standings。なにげにやっかいなのが同点での名前辞書順。得点と名前のペアでソートしてから名前を出力すれば良かったんだけど、名前に変換する前の数値の状態でソートして間違えた。一番複雑そうなサンプル3の出力だけ比較して一致することを確かめていたのだけど、厳密な比較をサボったそれ以外の2つのサンプルがどちらも合っていなかった。1ペナ。■D 問題 Repeated Sequence。数列を前から順番に処理しながら現在の要素を終端とするすべての累積和を列挙することができる。あとは N 項の和の余りをとったり、A 数列を2サイクル処理したりすることに注意する(数列を1周以上するケースや、N=7 のとき、A6+A7+A1+A2 のような累積和を対象に含めるため)。■E 問題 Takahashi is Slime 2。高橋くんスライムに隣接するマスをプライオリティキューに入れて、最小のものから取り出して併合する。■精進。F 問題 Double Sum 2。えっとね、つい最近、この問題と全く同じように数列を 0/1 で分類して数え上げる問題が出たと思うんだよね。時間外に考えてみてそれでも解けなかった問題なのでこの F 問題も解けないのがある意味当然だったのだけど、今日は時間はオーバーしたけど AC までたどり着けた。まず、trailing zeroes の数が異なる要素同士の和の f 値は簡単に求まる。一致するもの同士をどうするか。末尾の 1+1 の繰り上がりを考慮に入れたうえで、その次のビットを見る。一致していればそのビットが1に確定し、f 値が計算できる。異なっていれば、繰り上がりを考慮したうえでさらに次のビットを見る。提出 #60779596 (AC / 882 Byte / 608 ms)。数列を1つとる F 関数をまず書くんだけど、それにくわえて数列を2つとる FF 関数が書けるかどうかが AC に至れるかどうかの分かれ目だった。FF 関数に2つの数列をビットで分類した4つの変数 a0,a1,b0,b1 がある。10 通りの組み合わせのうち、a0×b0, a0×b1, a1×b0, a1×b1 の4つは答えに計上するけども、a0×a0, a0×a1, a1×a1, b0×b0, b0×b1, b1×b1 の6つは答えに計上してはいけない(これらはすでに F 関数で答えに計上されているので)。このように、0/1 で分類して 0×0, 0×1, 1×1 の組み合わせについて答えを計上する F 関数と、似ているけど異なる FF 関数がなかなか書けなかった。F 関数は FF 関数を呼ぶけど、FF 関数は FF 関数を呼ぶ再帰関数なので、FFFF 関数を定義する羽目には陥らないということも見通せなかった。F 関数の要求からとりあえず FF 関数を定義してみて、FF 関数が要求するものは FF 関数だったのでめでたしめでたしという流れ。■これかな? PAST18-K「2で割り切れる回数」。解けなかったんだよね。シグマの範囲がちょっと違うだけで同じ問題だ。今なら解けるだろうか。ちなみに、Ruby で 81 バイトで解けるらしいです(#60224722)。通った。提出 #60784486 (AC / 650 Byte / 301 ms)。長さから判断するに明らかに不器用な数え方をしているけども、今日の F 問題と同じ構成で解けた。F 問題も K 問題も制限時間が4秒5秒なんだけど、想定解法ではない? 1秒しかいらないよ。


2024年12月07日 (土) [AtCoder] 今日は大和証券プログラミングコンテスト2024(ABC383)があった。解ける問題を順当に解いてもぞもぞしたレート変動。これを冴えない結果という。ABC問題の配点がそろって上振れしているのを警戒していたのだけど、手が忙しいという点を評価しての上乗せだった。■A 問題 Humidifier 1。ヒュ…ミ…ディ…? この感じの読めなさは湿度に関する単語だということを知っている。問題文に加湿器とあるからそれだろう。もうひとつ読めない書けない発音できない単語といえば血圧計で、スフィグモマノミターという。どうでもいい話。こういう考えに邪魔されながら問題を解いてるんですよ。今日の T はソートされています! 変数 t(ime) と v(olume) を持って順番にシミュレートする。■B 問題 Humidifier 2。3連星の2つ目。全探索の愚直カウントで OK な制約。問題をよく読まないから床の座標だけでいいのに机の座標を用意したり削除したりしていた。■C 問題 Humidifier 3。オフィスの広さがさっきの万倍になりました。1メガの入力文字列はなかなかの大きさ。これって何アールかな、何ヘクタールかなとどうでもいいことをまずは考えていた。たしか 100M×100M が1アールだったと記憶している。単位の換算表が書かれた青っぽい下敷きを学校で使っていた。ミリバールはもう載っていなかったと思う。BFS をやります。■D 問題 9 Divisors。D 問題らしい問題。E より難しくて 40 分かけた。約数の数が奇数というのが最初のポイント。これって平方数かなと考えていくつかの数について約数を列挙してみてその通りだと思った。N 以下の平方数で約数が9個のものを Integer#prime_division で見つけようとしたけど、最大ケースのサンプルが通らない。200 万回繰り返すには素因数分解のコストは高すぎるらしい。もうちょっと考えてみる。約数の数が9個ということは、素因数分解したあとの形が p1*p1*p2*p2 になるものしかないのではないかと考えた。約数の数っていうのは素数ごとの (指数の値+1) をかけあわせたものなので、9になるのは (2+1)*(2+1) だけなのではないかと。ここでも平方数だ。2乗なのか4乗なのかもうわけがわからないよ。素数の2乗を列挙するだけで済むので時間は間に合うようになったけど、最大ケースのサンプル2が合わない。10 いくつかだけ少なく出る。時間オーバーの素因数分解解法の答えは合っているので、9=(2+1)*(2+1) の部分で漏れがある。9=(8+1) のケースが漏れていた。2乗4乗の次は8乗だってさ。もうわけがわからないよ。こうなるとサンプル1の嫌らしさに気がついてしまう。最初の8乗数が 256 だから、サンプル1の N=200 は絶妙に少ない。そんなこんなで 40 分間たいへんな思いをした。コーディング部分は列挙して二分探索して足すだけで何も難しくない。Ruby で 307 ms の提出があるなか自分のは 1004 ms かかっているあたり、考察がまだ甘いのだけど、もう考えたくないのだ。■F 問題 Diversity。配点が E より 25 点だけ上なのでまずは F 問題を読んだ。DP。パラメータが多い。制約は N が 500 以下な点を除いて甘くない。特に色の種類が N 以下と全く限定されていないので、どの色がすでに選択済みかというビットフラグを状態のキーにはできない。色の扱いが問題だと思った。色ごとに DP をして価格と効用がそろって上昇するように商品グループを列挙しておいて、そののち価格と効用についての DP をするのかと思った。だけど後段の DP で扱う商品群がどれだけの大きさになるのかわからない。商品を組み合わせたものをさらに組み合わせようとしている。ここらで E 問題へ。■E 問題 Sum of Max Matching。頂点数も辺の数も少なくないグラフ。パスに含まれる辺の重みの最大値を考えるということは、回り道をしてでも軽い辺を使うべきだということ。UnionFind で軽い辺から使って徐々にグラフを拡張していくのかな。特に短くない2つの数列 A と B が与えられて、その組み合わせの最小値を答えるという。各頂点は A 数列か B 数列のどちらかに含まれるか全く含まれないかで、どちらかに複数回現れることもある。グラフを拡張しながら連結成分内で A-B ペアを作ろう。具体的なペアを考えるには A,B 数列は長すぎるけど、連結成分ごとに余っている A(B) 数列要素の数を記録しておくだけでよい。A 数列の要素と B 数列の要素を貪欲に消費して損をしない。F 問題に寄り道していた時間を含めても提出まで 21 分だから、D 問題より早い。これは不思議のないことで、UnionFind を使うからクラスカル法を使うからという理由で E 問題に配置されている問題は、のーみそこねこねな D 問題より型にはまっていて解きやすいことがある。今日は得をしたけどこれとは逆に、LazySegTree を使うからという理由で F に配置されている問題は、diff が低い割に配点が高く、だけど Ruby で参加している自分は TLE にならない遅延セグメント木の実装を持っていないので撤退するしかないということで大損をする。くやしいね。■F 問題。色で商品をソートしておいて、色が切り替わるところで DP テーブルを切り替えることにして、あとは普通に DP をするだけだったのだろうか。DP は1回だけで良かったんだろうか。どんだけ考察が早くても残り 20 分で実装できる DP ではなかったけども。■■■たぶんだけど、1アールに関連して覚えている 100 という数字は、掛ける前の数字ではなく掛けたあとの数字ではなかったか。つまり、10M×10M = 100M^2 = 1アール なのではなかったか。そうすると1ヘクタールに関連付けて覚えている1万という数字が、100M×100M = 10000M^2 = 1ヘクタール ということになっておさまりがいい。自分の生活に一切関わってこなかった知識なのでわざわざ調べませんけども。■C 問題に関連して多始点 BFS というワードを見かけたので調子に乗ったことを書くんだけども、始点の数を区別することに意味がありますか? 移り変わるキューの中身をのぞいてみる。キューの中に始点(距離ゼロの頂点)が詰まっている状態がスタート。そこから距離ゼロと1の頂点が詰まっている状態、距離1の頂点が詰まっている状態、距離1と2の頂点が詰まっている状態、距離2の頂点が詰まっている状態、距離2と3の……状態が次々と現れる。距離ゼロの頂点だけが唯一でなければいけない理由はどこにもないと思うんだよ。同じ距離の頂点が1個だろうが複数だろうがキューの中で整然と列をなすからプライオリティキューなしで BFS が成立している。■精進。F 問題。昨日「どんだけ考察が早くても残り 20 分で実装できる DP ではなかったけども」と書いたわけなんだけど、ARC189 が終わったあとで書き始めたら 11 分で完成したよ。提出 #60595097 (AC / 253 Byte / 1030 ms)。ひとひねりあっただけで初歩的な DP でしたね。ひとひねりでてきめんにやられてしまうところに応用力のなさが現れている。BFS の始点が複数になってやられるのと同じことだよ(調子に乗ってごめんなさい)。


2024年12月02日 (月) 訪問予定のお客さんから予定していた時刻には帰宅できていないと連絡がありました。帰宅予定は X 時 15 分だそうです。どうしますか?■自分は 15 分を過ぎた頃に伺いますと言って 20 分に到着する予定を立てるんだけど、15 分に行くと言って 15 分に到着する予定を立てる人や、5分10分前に到着して待つ(待たせない)ことを良しとする人ばかりで同意を得られない模様。■自分の行動背景。15 分に行くと伝えたら、15 分ではなく 15 分までに帰宅していなければいけないと焦らせてしまうのではないかと考える。そのように考えない人のことを自分は気にかけるつもりがないし、その必要もない(だってそのようには考えないのだから)。遅刻した人を待ち構えることについて。それは待たせてしまったことに負い目を感じさせる行為だと考える。「待った?」「今来たところ」の様式美が自分は好きだ。自分の行動の失点は何か。すでに最初の予定時刻を過ぎているのに、さらに帰宅から5分かそこら待たせてしまうかもしれない。しかしさっきから書いているように、人を待たせているのに自分は待ちたくないというような厚かましい人のことを自分は気にかけるつもりがない。善良な人のことを気にかけている。ただし、そのための最適な行動が何かについては自信がない。■ここに書かれていることから自分という人間について3点読み取れることがある。というか結局自分のことしか書いていないといえる。それは、焦ること(時間に追われたくないこと)、負い目を感じさせられたくないこと(わがまま!)、15 分に帰ると言ったら真実 15 分にしか帰れないこと(方便としての嘘がないことそれを想定しないこと)。5分に帰るつもりで 15 分には帰れると伝えるのは別の話(これは嘘ではなく条件を緩めた本当のことなので)。ここからもう1点読み取れること。自分は善意からであれ利己心からであれ、嘘をつくコストを一切負担したくないということ。そのコストを負担しきれないことをすでにいやというほど知っている。話がそれるけど、「いやというほど」を漢字にすると「否という程」の一択になるらしい、ATOK(+広辞苑) によると。「嫌」じゃないんだ、知らなかった。イヤとイナヤの違いなんてわからないからしかたないね。あ、5つ目。今こいつ自分のことを善良な人間とイコールで結びやがった。


2024年12月01日 (日) [AtCoder] 昨日あった AtCoder プログラミングコンテスト2024(ABC382)について。精進を済ませてからにしたかったけど目途が立たないのでとりあえず。■A 問題 Daily Cookie. を数えるか @ を数えるかして、D を足すか引くかする。■B 問題 Daily Cookie 2。後ろから書き換える。愚直に N^2 の時間をかけて大丈夫。String の場合は検索開始位置が渡せるのでケチって線形時間にもできる。Array で検索開始位置が指定できないのはスライスを使えってことなのかなと思うけど、添字の調整が面倒くさいからやらない。■C 問題 Kaiten Sushi。配点がちょっと高い。上流にいる人が食べたいものをすべて食べてしまうという容赦ない設定は流し索麺を思い出す(Somen Nagashi)。あちらは離席して食べる時間があるけども、こちらは容赦なき総取り。人の列が減少列になるように間引いてから二分探索をしたけど、寿司の方をソートしてしまえば二分探索はいらなかった。計算量のオーダーは変わらないので実装はお好みで。■D 問題 Keep Distance。すべて出力しろと言っているのだから、愚直に列挙して間に合う制約になっている。DFS が書けますかという問題。あ、嘘嘘。愚直に列挙したら最大ケースが終了しなかったので先を見て予め列挙範囲を限定する必要があった。無駄なく列挙しないといけなかった。■E 問題 Expansion Packs。2乗の DP が許される制約(?)。解答形式が小数だからサンプルも小数で書かれているし、サンプルの2が自己ループを含むものになっているおかげでデバッグが捗って助かった。何をしたか。現在持っているレアカードの枚数 R とそこに至る確率をベースとして、今開ける1パックの期待値(=1パック×確率)を答えに足し、レアカードが R+X 枚になる確率を配っていきたい。そうすると1パックあたり X 枚のレアカードを得る確率を予め計算しておく必要がある。そうすると1パックにレアカードが0枚で足踏みしてしまう場合があることに気がつく。こういうのは具体的にどうするとうまくいくかを考えた。1パックあたり3分の1の確率でレアカードが0枚に終わるケースで考えると、1回に2分の3パック開ければレアカードが期待できる。レアカードが入っている前提ではレアカードが X 枚入っている確率は、分母(全体の場合の数)が減っているのだから最初に求めた数字より大きくなるはずで、1/(1-1/3) の式で倍率を表すと丁度いい大きさになるなと考えた。要はレアカードが0枚の場合を含む全事象からレアカードが1枚以上の全事象への分母の減少率の逆数。しかし! TLE が解消できなかった。C++ で書き直したものはループの範囲を限定したりといった小細工なしでも 39 ms で AC だったけど(#60354761)、時間内には間に合わなかった。制約に泣かされた。Ruby で通している人が1人いたので、これは泣き言なんだよなあ。■F 問題 Falling Bars。消えない回らないスライドしない、落ちるだけのテトリス。区間更新区間取得のセグメント木の最も基本的な使い方がわかりますかという問題。残念ながら区間更新ができるセグメント木を持っていないので、即座に撤退して E 問題の TLE 解消に戻った(解消できなかった)。あまりにもストレートな問題なので、区間更新ができるセグメント木を書くいい機会かなと思った。以前読んだ競プロに関する翻訳された PDF (現物をなくしてダウンロード元も不明) のおかげで、トップダウン式のトラバースが自分の実装に欠けていることがわかっている。セグメント木を最初に雰囲気で実装したときに、末端から LCA までを辿るようなアクセス方法になった。だけど遅延された(区間)更新が伝播するのは根から末端に向けてなので、ボトムアップ式のアプローチはまったく役に立たない。トップダウン式の辿り方をでっちあげて区間更新ができるものをがんばって実装したけど、TLE だった(#60355045)。もうちょっと実装を洗練させたり無駄を省いたり手抜きをしたりする余地がないか考えてみたいけど、とりあえずここまで。■F 問題。通った! 提出 #60379219 (AC / 1143 Byte / 1869 ms)。さっきの TLE で再帰呼び出しをしていた4行を直接インスタンス変数を書き換えるように変更したら間に合った。今は 0 とか max とかをあちこちに(じか)に書いてるけども、これを汎化すると TLE の危険が増すんだよなあ。今で TLE まで 131 ms しか余裕がない。あと、今回は max だからごまかせてるけど、モノイド(?)が扱えるようには気をつかっていないので、簡単な置き換えだけでは乗せられないと思う。「遅延評価セグメント木に載せられるのは、モノイドに作用と呼ばれるものを付け加えた「作用付きモノイド」です」ということも今読んで知ったぐらいなので。■■■つづけて ABC357-F「Two Sequence Queries」に挑戦しているけど、概ね合うけど合わないものもあるという感じ。そして TLE が避けられないのは間違いない。だって1点更新のセグメント木で凝ったマージをするためにブロックを与えただけでもすぐ TLE になるのだから(いわんや~をや)。必要に応じて定義していったら演算が3つになったけど、こういうものなのかな。1つ目は普通のセグメント木と同じで左右のセグメントを連結するもの。2つ目が区間に対する更新。3つ目が区間に対する更新の更新(3を足して6を足すなら9を足すことにするみたいな)。■■■E 問題。もう C++ で通しちゃったし TODO として覚えておけないだろうから他の人の Ruby での提出を見た。みんな require 'numo/narray' していた。うん、それはね、Rust も Crystal も numo/narray もローカルに、古い Windows にインストールできなくて試行錯誤できないから捨ててるんだ。あきらめがついてすっきりした。■E 問題。あきらめたと書いたそばから通っちゃったね。提出 #60486554 (AC / 355 Byte / 1966 ms)。しょうもないなあ。コードテストで判断すると、制限時間が3秒なら TLE だった提出も TLE ではなかった。TLE と AC の違いはアルゴリズムの違いではなく、スクリプトの記述の違いでしかない。だからしょうもない。でも飛び道具なしのピュア Ruby でも不可能な制約ではなかったと自分で証明してしまったんだよな。なんだよくやしいなあ、あきらめがつかないじゃないか。■■■@2024-12-18 ABC357-F の精進について 20241218 に書いた。ついでに書くけど、さっき通ったと喜んでいた ABC382-F への自分の提出 #60379219 (AC) にはバグがある。61 行目のセグメント木の初期化サイズが間違っているので、N が W よりたっぷり小さいときエラーが出る。


2024年11月22日 (金) [AtCoder] 今日は金曜日だけど AtCoder Beginner Contest 381 があった。F 問題はたぶん青 diff かなあ。それが今日の1問だったら解けると思うんだけど、A から F までの6問のうちの1問だと、まあ無理。11月11日がポッキーの日だったのかな、知らないけど。で、今日はわんわんにゃんにゃんの日なのかな、知らないけど。■A 問題 11/22 String。問題文が難しすぎます。例を見て把握してから理解に間違いがないかを定義に戻って確かめるのが良いと思う。正しい 11/22 文字列を作って入力と比較した。■B 問題 1122 String。こちらの問題文(というか式)はやや読みやすかった。文字の uniq を取って倍加して入力と比較した。■C 問題 11/22 Substring。前後の 11/22 文字列がオーバーラップすることはないので、正規表現で 1*/2* を拾い出してからスラッシュの位置を探して計算した。なんでか 10 分かかっている。■D 問題 1122 Substring。やることが多いよね。まずペアの列を複数切り出したんだけど、同じ値が3つ以上連続している場合に注意が必要。その部分でペアの列を切って新しい列を始めるのだけど、どちらの列にもペアを登録することになる。たとえば 1 1 2 2 2 3 3 が与えられたとき、得られるペアの列2つは 1 22 3 になる(同じ数字の繰り返しは省略)。2 と 2 のペアが前後のどちらの列にも属している。その次にペアの列に対して同じ値を含まない最長の範囲を求める。現在の値を右端とするとき左端がどこまで伸ばせるかを考えた。最初は値ごとに直前の位置を記憶しておくだけでいいかと思ったけど、そうではないのだな。たとえばペアの列が 1 2 3 2 1 だったとき、右側の 1 から左側の 1 の直前までを切り出すと 2 3 2 1 になって違法。値ごとに直前の位置を記録するだけでなく、その最大値を1つメモしておく必要があった。RE/WA を1回出しつつ 26 分かけた。難しいし妥当だと思う。■E 問題 11/22 Subsequence。25 点だけ配点が上の F 問題に先に取り組んだけど追い返されてきた。スラッシュの位置にそのスラッシュを中心とする 11/22 文字列の長さを記録しておけば、(区間の両端に近いスラッシュだけちょいちょいと調整すれば)セグメント木の区間クエリで答えが出せると思ってしばらく無駄な時間を費やしていた。何を勘違いしていたか。「(連続とは限らない) 部分列」で 11/22 文字列を構成するということは、スラッシュとスラッシュで 11/22 文字列が区切られるわけではない、ということがわかっていなかった。スラッシュを飛ばしてその向こうまで 1 なり 2 なりの文字を拾い出して構わない。ということを理解すると、スラッシュの位置ごとに左に1がいくつあって、右に2がいくつあるかということだけが重要。クエリで範囲が与えられたとき、どのスラッシュにとっても同じ数だけ1と2の利用が制限される。範囲内のスラッシュに対して二分探索で左右の1と2の均衡点を探る。こういう二分探索は少し前に初めてやった(ABC364-D「K-th Nearest」、20240727)。2つの均衡点(m0, m1)を取り違えるタイポで WA を1回出しつつほぼ1時間かけた。終了5分前に WA が出たときは目の前が真っ暗になる思いがしたけど、上から読み直して運良く見つけられた。F 問題を考えていた時間とセグメント木を使っていた時間が無駄になった。3、40 分で解きたかったね。■F 問題 1122 Subsequence。A の値域が 20 以下という制約からどういう DP がやれるか考えてしまって考えが深まらなかった。D 問題でやった DP と、E 問題で気がついた「都合の悪い要素を飛ばして伸ばせる」という点がヒントになると思うんだけど、未だまとまらず。現在の要素を右端として直前の同値の要素からどれだけ左に伸ばせるかを考えたいんだけど、それをするのに何をキーにして状態を記録するのかが不明。■値が 20 種類しかないということは、最長でも 20 までしか伸ばせないということだ。ということは? 何ができる? 長さが問題にならないなら幅が 1<<20 でも問題ないということで、bit DP か?■五線譜ならぬ 20 線譜があって、隣接する同値の2要素を繋いだ区間が線上に乗っていて、20 本の線からオーバーラップのない区間を選んで繋ぐ。同じ線からは1つの区間だけ。■■■精進。F 問題。O(AN) の方針に行き詰まって O((2^A)A) の ビット DP に方針を定めたとして、遷移がわからなかった。ところで、状態のキーがこれまで使用した値ペアだとして、何を記録するのか。これは N 要素のどこまでを使用してその状態に至ったかの最小値。ということを整理しているうちに TSP が降ってきた。巡回セールスマン問題と同じ遷移で解ける。提出 #60111625 (TLE) のち 提出 #60113392 (AC / 612 Byte / 1405 ms)。やっぱり今日の1問レベルの歯ごたえがあった。Crystal での提出を見てると E 問題の AC から7分半でこの F を通している人がいるけども(#60070912)、それは頭がおかしい。自分はこの問題を反射では解けないし、指を動かすだけでもそれ以上の時間がかかるのは間違いない。TSP 問題は3問ほど解いたことがある(だけど未だに苦しむんだよ)。たとえば ABC180-E「Traveling Salesman among Aerial Cities」(20201018p01.02)。これ水 diff 下位の難易度しかないことに驚く。この F 問題は青 diff 下位だったけど、目くらましが目くらましとして機能しないレベルの人にとっては、青も水も変わらず典型パターンを当てはめるだけの問題になってしまうのか。それも難なくやってのける。■■■A 問題。ややこしいし効率が悪いしやる意味はないんだけど、あえての正規表現。提出 #60163766。パターンは ^(1\g<1>2|/)$。Ruby ならできます。同じパターンを C 問題でも使おうとしたけど、N≦200000 では TLE が不可避だった(提出はしていない)。■■■F 問題。それとさっき挙げた ABC180-E Traveling Salesman among Aerial Cities。遷移まで含めて bit DP と呼ばれてるみたい? 「集合 S をビット表記により 0,1,…,2N−1 までの自然数にエンコードしてしまうと、S=0,1,2,… 順にループするだけでトポロジカル順序が守られることなどから、実装が簡潔になります。この実装方法から bit dp とも呼ばれることの多い手法です。」([AtCoder 参加感想] 2020/10/17:ABC 180 | maspyのHP)。自分が bit DP と認識しているものはメモ化再帰とよく結びつくもので、状態をビットフラグで表すことで順序に関する情報を落として再計算を省くというもの。遷移はそのつど再帰関数を書くときに考えている。だけど bit DP というだけで今回のような遷移が引き出せるべきなんだろうか。


2024年11月12日 (火) 昨日あったこと。目覚ましをセットして昼寝をしたら寝坊して遅刻したみたいになった。スマホの時計が8分遅れていた。朝にバイクの時計が3分早かったからスマホの時計に合わせていたものだから、バイクの時計も狂っているかと思って確認したらそんなことはなかった。つまり、朝から昼の半日でスマホの時計が8分狂っていた。そんなことってある? ちなみに、当初から2分程度(1分1秒から2分59秒のあいだ)狂うことがあるのは確認していて、「ネットワークの時刻を使用する」を一回オフにしてオンに戻すことで修正することが定期的にある(年に1回くらい。土曜の夜9時に気がつくことが多い)。電話をしないと(時刻合わせがされなくて)狂うという人がいたけど、月に数度は通話をしている。数日前にも通話をしていた。ネットで検索すると Wi-Fi に繋がっていないと時刻合わせがされないことがあるとあったが、移動時を除いてほぼ常に Wi-Fi に繋がっている。ただ、データセーバーが有効だからバックグラウンドで Wi-Fi を使っての時刻合わせができていない可能性はある。しかしこれは半日で8分狂う理由にはならない。オフラインの内蔵時計だけでも月に30秒ずれるかずれないかくらいの精確さはあるでしょ。誤った時刻に合わせた結果狂ったのではないか。位置情報がオフだと誤った時刻に合わせられることが稀にあると書いているところがあった。たしかに位置情報はオフだ。「ネットワークから提供されたタイムゾーンを使用する」はオフでタイムゾーンは日本標準時で固定なんだけど、この設定でおかしなタイムゾーンの誤った時刻を表示するケースがある? ところで、このタイムゾーンの設定は時計アプリからアクセスしているけども Android の設定なのだな。そして時計アプリ自体もタイムゾーンの設定を持っている。そしてそこには不穏な表記がある。いわく、「自宅の時計を自動表示(時差のある場所にいるときに自宅の時刻を追加する)」「自宅タイムゾーン GMT+9:00 東京、大阪」。自宅タイムゾーンの設定は Android のタイムゾーン設定とは連動していない別個の設定だが一致しているので問題ない。しかしアプリの表記を信用するなら、このアプリは第一に現地時刻を表示しようとする。現在地を見失って狂った時刻を表示する可能性がないとは言えない。アプリがどうやって「時差のある場所にいる」と判断するのかわからないから可能性があるとしか言えないが。現在地を見失ったとして時差8分のタイムゾーンはないけどね。じゃあどうやって狂う? もうどの瞬間にもスマホの時計が信用できない。■今日あったこと。本を7冊買ったら2冊はもう持っていた。今日の自分が興味を持つ本に、2年前の自分と4年前の自分が興味を持っていたというのは大いにありうること。一応書名で持っているかどうかを検索したんだけど、ウソの字に2種類ある(「嘘」「噓」)からと仮名で検索したのが良くなくてヒットしなかった。今思えば2種類あると意識に残っていることそのものが、過去にその書名を(購入記録として)登録したことを意味していたのだった。愚か。


2024年11月10日 (日) スズキが初公開! 新型デュアルスポーツバイク『DR-Z4S/SM』、世界展開もあるぞ…EICMA2024 | レスポンス(Response.jp)」■ホンダの CRF250L しか残っていないところに一抜けしていたスズキが帰ってきた。最初のバイクがスズキの DR250R だったから(写真1, 写真2)、待っていました。ひと昔前はこのサイズは7、80万円だったけど、今は 100 万円を超えるのかなあ。ていうかね、DR-Z400S の 2001 年のカタログを持ってるけども、値引き前のメーカー希望小売価格で 65 万円しない。それが今だと? それが 100 万でも 130 万でも他がもうないんだな。■「DR-Z4S - webオートバイ


2024年11月09日 (土) [AtCoder] 今日はトヨタ自動車プログラミングコンテスト2024#11(AtCoder Beginner Contest 379)があった。いい日ではあったがそれはつまり6問目まで解ける問題が並んでいたということであり、えっと、退屈な問題セットだったということなのでは? 退屈な問題しか解けないのが私です。■A 問題「Cyclic」。標準入出力が扱えますかという問題。AtCoder 初参加の時は知らなかったからリファレンスを引いた。■B 問題「Strawberries」。前から貪欲に。■C 問題「Sowing Stones」。難しい。N 個のマスを順番に処理することができないのが難しい。石の入ったマスに着目して計算で石を配らないといけない。計算というのは等差数列の和。N マス全部を埋めなければいけなくて、石は右にしか配れないから、右の方にある石の山から順番に、現在右から何マス目まで石で埋まっているかを記録していった。右から隙間なく敷き詰めていくことしかできないからね。これを左側から処理しようとすると、いろいろと保留するものが出て来てややこしいと思った。13 分かけて書いた最初の提出が WA だった。問題文を読み直したら「ちょうど」って書いてある(「N 個のマスすべてに石がちょうど 1 個ずつ入っている」)。石が余る場合に間違えていた。修正に5分。N マスすべてに石が配れるかは確認済みなので、石の総数が N であることをチェックするだけ。ペナルティ込みで 23 分かけた計算。難しいよー。■D 問題「Home Garden」。一転して簡単な問題。配列(生配列とポインタペアで十分)に植えた日を記録していく。収穫は先頭から順番に。4分半。■E 問題「Sum of All Substrings」。かつての ABC-D 緑 diff って感じの問題。まず、余りを取る問題でないことに驚いた。えっ。64 ビットに収まるんですか? (サンプルを見て)収まらないね。1の位から考える。S の各桁の数字は1の位として何回活用されるか。10 の位、100 の位としては……。繰り上がりも考慮して決めていく。提出までおよそ 30 分。書く量は 252 バイトでもすらすらとは書けない。■F 問題「Buildings 2」。よみがえる ABC372-D「Buildings」の悪夢 (「脳みそがスポンジ化している」「番狂わせの D 問題」「提出するまでほぼ1時間ぐだぐだやっていた」「問題が全然頭に入ってこない」「いったい何を数えるんだよー」「"ビル i とビル j の間にビル j より高いビルが存在しない" という i と j のペアを数えるんだけど、えっとね、i のビルの高さはなんにも関係ないんだよ」「理解したら実装は5分」)。慎重に問題とサンプルを読んで理解に努めた。基本的には自分自身を起点とする増加列を数えておけば良さそう。自分より低いビルも見ることができるんだけど、r より低いビルを l から見ることはできないので、それは数えても意味がない。l と r の高低にかかわらず r から見える r より高いビルの数が答えの候補になる。あと考えることは、l から r が見えない場合。答えはゼロではなく、あいだにある最も高いビルから見えるそれより高いビルの数が答えになる(この条件は r が最も高いビルである場合もカバーするので場合分けが消える)。ランダム入力と愚直解法からこのケースを見つけた。ABC372-D の記憶によって数えるべきものがはっきりわかっていたから、見つけたケースの解釈で迷うことがなかった。あとは増加列を数えるのに LIS をやるポカをした。スタックを1本持って長さを数えるだけでいいのはさっき挙げた Buildings と同じはずなんだけど、なんで同じにできなかったんだろうなあ。最初の提出 #59612302 (WA) を書くのに 20 分かけて、デバッグに 20 分かけた。提出 #59621904 (AC)。■G 問題「Count Grid 3-coloring」。10 分も残っていないので問題を読むだけ。左の数字と上の数字を参照して1,2,3の場合の数を数える DP かなと思ったけど、制約が3乗を許容しているし制限時間も長めの3秒なので、何かが抜けているか全てが間違っているかのどちらか。■コンテスト成績証。青パフォ 1763。■あっ、F 問題の問題名が Buildings 2 だ! そうか、問題名で自己言及していたのか。■■■C 問題。左にある石の山から処理をしようとするといろいろ保留することになって面倒そうと書いたけど、実際には左からやった方がシンプルになった。提出 #59709275 (左から / 204 Byte)。提出 #59582960 (右から / 280 Byte)。


2024年11月02日 (土) [AtCoder] 今日は AtCoder Beginner Contest 378 があった。解ける問題が当たり前に解けなくて無駄に WA を重ねた。実装が下手!■A 問題 Pairing。Array#tally を使うところまでは良かったけど、同じ数が4個ある場合、2個3個ある場合と場合分けをしたのが制約に甘えている。個数を2で切り捨て除算したものを合計するのが正解。他の人の提出を見てこの式は頭が良すぎるだろうと思ったけど、なんのことはない、それが当たり前のやり方だった。作れるペアの数を数える問題なのだから。■B 問題 Garbage Collection。10 分かけました。1つの式でパッと答えを出したいと思ってあれこれやったけどだめだった。ステップを踏んで数えた。■C 問題 Repeating。問題文が難しかった。「Ai​ と等しい要素が i の直前に出現した位置を Bi​ とする」とあったが、等しい要素を A 数列から探すのか B 数列から探すのかわからなくてフリーズしてしまった。サンプルで理解したけども、読み飛ばして「より正確には」以下を読むのでも理解できた。だけどそこまでたどりつかずにぐるぐるとスタックしてしまった。わかれば値の範囲を見て Hash でメモ。■D 問題 Count Simple Paths。計算量で難しさを出してくるのが D 問題というイメージなので、愚直 DFS が通るのは甘々です。だけど BFS は書けるけど DFS はなんか苦手という時期が自分にもありました。■E 問題 Mod Sigma Problem。解けてないよ。6問解く実力がなくて F 問題が 25 点だけ上なら F 問題を先に解かない理由がないよ。■F 問題 Add One Edge 2。単純グラフというのは自己辺なし多重辺なし。単純グラフというのは自己辺なし多重辺なし(2回目)。問題文を読んでるときにこの通りに補完しているが、ABC なんだからそこまで書いてもいいと思うんだよね。知らなきゃ解けないという問題は門前払いされたようで面白くないよ。それが概念でなく単なる言い替えレベルの用語がどう定義されているかというだけのことであればなおさらしょうもなくて面白くない。次数2の頂点同士を結んでその LCA までのパスがすべて次数3であるか、LCA が次数2の頂点の一方であるかという場合を数える。とにかく実装が下手だった。WA (隣接している次数2の頂点を結んでしまっていた。それは多重辺)、WA (葉を刈り取る DP をしているのに処理順が LIFO だった。20241019と同じミス。手癖で書いてるんじゃないのよ。pop かな shift かな pop でいいよねと考えた結果なのが救われない)、WAWAWA (葉を刈り取る DP をしているのだから、1を仮の根としたときの親に処理を流すのは間違いなのよね。この場合の根とは最後まで残った1ノードのことなのだから。一番深いところから積み上げる DP なら間違いではなかったし、脳内イメージではそうしていたんだけど、実際にやってることがちぐはぐだった)、AC (再帰関数で再実装したら AC だった。だって何度問題を読み直してももう考えることが残っていなかったので、原因がわからなくても実装が悪いことが明らかだった)。■レートは横ばい。デバッグとペナルティで失った 50 分が痛い。■■■精進。E 問題。累積和とか転倒数とか BIT とかのワードを見かけてもいまいちピンときていなかったが、ある動画でエスアールヒクエスエルが負と聞いてやっとやるべきことがわかった。それを正しくやるのにも散々迷走して凡ミスをして苦しむんだけど。提出 #59430244 (AC)。■■■精進。水 diff ながら抜けていた ABC221-E LEQ。さっきの E 問題を解いたあとだと普通に解ける気がして、普通に解けた。提出 #59440817 (AC)。ABC378-E とは類題ってことでいいのでは? 自分は感覚とかイメージとかのふわっとしたもので問題を解いているので(○○の△△は二分探索(を疑う)みたいなトリガーを記憶しておくことも適切に引き出すこともできなくて、二分探索の雰囲気がするから二分探索をしている。例「二分探索っぽさがあるよね」)、式を操作したり式を見て糸口を見つけるということが苦手というか、まったくアプローチができていない。そういう苦手を突くという点で類題だと思った。この問題では2の冪乗というものについて、足し合わせてみたり、足し合わせたものをまとめて割ったりするとどうなるかな、何の問題もなく個別に計算したのと同じ結果が手に入るなということを確認するだけで解答が書けた。昨日まではそれができなかった。ある範囲の連続部分列の和が Sr-Sl であると、それが mod を取ったあとだとどうなるか、それをどうするかと考えてみることができなかった。そういうアプローチが存在していなかった。


2024年10月27日 (日) 【速報】自民・麻生太郎氏「物価が上がり始めた。それで給料も上がったろ?間違いなく、政策が当たったからだろうが!」 → 聴衆から歓声 : 暇人\(^o^)/速報 - ライブドアブログ」■円の価値が薄まって取引される額面はたしかに上がったかもしれないけど、預貯金の額は変わらないし、賃金の上昇も追いつかないし、デフレに応じた賃下げができないからって、代わりに円の価値を下げただけじゃないですか。じゃあやるべきではなかったかというと、自身の価値を現在の相場で額面にかえられる現役世代の方がリタイアした人より有利な立場にあると思うんだけど、どうなんだろう。よくわからないでテキトー書くけども、株式分割を繰り返したライブドアのまねをするなら円を刷り続けるのもいいんじゃないの。価値と額面が調整されて均衡するまでの時間差で短期的には錬金術が成功しそう。錬成するのが金であれ紙幣であれそこらにあふれたものを欲しがる人はいずれいなくなるだろうけど。まずは日本人が円を危険資産とみなして欲しがらなくなるよね。もうなってるか。