読書記録(2021)

kotatsugame.hatenablog.com

1月

  • 1日
    涼宮ハルヒの直観
  • 2日
    セプテムレックス
  • 3日
    いわくつき魔族教師と天使候補生
  • 4日
    人生∞周目の精霊使い
  • 5日
    クラスの大嫌いな女子と結婚することになった。
    僕はリア充絶対爆発させるマン
  • 6日
    僕はリア充絶対爆発させるマン2,3
  • 8日
    見習い巫女と不良神主が、世界を救うとか救わないとか。
  • 9日
    デスゲームから始めるMMOスローライフ
  • 10日
    デスゲームから始めるMMOスローライフ2
  • 11日
    デスゲームから始めるMMOスローライフ3
  • 20日
    デスゲームから始めるMMOスローライフ4
    江戸の花魁と入れ替わったので、花街の頂点を目指してみる
  • 30日
    転生魔王の大誤算2

2月

  • 5日
    あくまでも探偵は
  • 11日
    幼馴染で婚約者なふたりが恋人を目指す話1
    日常ではさえないただのおっさん、本当は地上最強の戦神7
    継母の連れ子が元カノだった6
  • 16日
    暇人、魔王の姿で異世界へ12
  • 17日
    シェアハウスで再会した元カノが迫ってくる
  • 19日
    数学者の夏
  • 20日
    ホラー女優が天才子役に転生しました2
    義妹生活
  • 21日
    裏社会最強の男、終末異世界を愉しむ。
  • 23日
    ワールド・ティーチャー14
  • 24日
    盤上の向日葵 上
  • 25日
    盤上の向日葵 下
  • 28日
    魔王2099

3月

  • 10日
    自称Fランクのお兄さまがゲームで評価される学園の頂点に君臨するそうですよ?10
  • 12日
    りゅうおうのおしごと!14
  • 13日
    ねえ、もっかい寝よ?2
  • 23日
    最強魔法師の隠遁計画12
  • 24日
    現代社会で乙女ゲームの悪役令嬢をするのはちょっと大変2
    お隣の天使様にいつの間にか駄目人間にされていた件4
  • 25日
    公女殿下の家庭教師8
    暗殺者である俺のステータスが勇者よりも明らかに強いのだが4
  • 26日
    転校先の清楚可憐な美少女が、昔男子と思って一緒に遊んだ幼馴染だった件
    幼馴染の妹の家庭教師をはじめたら3
  • 27日
    ブラックな騎士団の奴隷がホワイトな冒険者ギルドに引き抜かれてSランクになりました3
  • 30日
    文字渦
    時々ボソッとロシア語でデレる隣のアーリャさん
  • 31日
    僕が答える君の謎解き

4月

5月

  • 2日
    D級冒険者の俺、なぜか勇者パーティーに勧誘されたあげく、王女につきまとわれてる2
    やはり俺の青春ラブコメはまちがっている。14.5
  • 3日
    ルミナス☆アイドル
  • 10日
    元スパイ、家政夫に転職する2
  • 12日
    魔王2099 2
  • 13日
    隣のクーデレラを甘やかしたら、ウチの合鍵を渡すことになった2
  • 14日
    辺境都市の育成者3
    両親の借金を肩代わりしてもらう条件は日本一可愛い女子高生と一緒に暮らすことでした。2
  • 15日
    株では勝てる俺も、カワイイ女子高生には勝てない。
  • 18日
    恋は双子で割り切れない
  • 19日
    雪中の花は、軍神を偽る
    才女のお世話1
    クラスの大嫌いな女子と結婚することになった。2
  • 22日
    午後九時、ベランダ越しの女神先輩は僕だけのもの2
  • 23日
    犯罪社会学者・椥辻霖雨の憂鬱
    レーゼンシア帝国繁栄紀
  • 24日
    レーゼンシア帝国繁栄紀2

6月

  • 25日
    ネトゲの嫁が人気アイドルだった1
    異世界でチート能力を手にした俺は、現実世界をも無双する8
  • 27日
    クラスに銃は似合わない。
    VTuberなんだが配信切り忘れたら伝説になってた

7月

  • 1日
    私立シードゥス学院II
  • 2日
    史上最強オークさんの楽しい種付けハーレムづくり5
  • 3日
    転生魔王の大誤算3
  • 6日
    居候先の三姉妹がえっちなトレーニングを求めてくる
  • 16日
    お隣の天使様にいつの間にか駄目人間にされていた件5
  • 17日
    幼馴染で婚約者なふたりが恋人をめざす話2
  • 23日
    サベージファングお嬢様
    ブラックな騎士団の奴隷がホワイトな冒険者ギルドに引き抜かれてSランクになりました4
  • 28日
    公女殿下の家庭教師9
    嘘と詐欺と異能学園
    推しが俺を好きかもしれない
  • 29日
    きみは本当に僕の天使なのか
    日本語が話せないロシア人美少女転入生が頼れるのは、多言語マスターの俺1人
  • 31日
    時々ボソッとロシア語でデレる隣のアーリャさん2

8月

  • 2日
    グッバイ現実世界
  • 3日
    大罪ダンジョン教習所の反面教師
  • 7日
    最強魔法師の隠遁計画13
  • 8日
    継母の連れ子が元カノだった7
  • 9日
    サイレント・ウィッチ
  • 10日
    幼女戦記8
  • 11日
    異世界管理人・久藤幸太郎
  • 12日
    異世界管理人・久藤幸太郎2
  • 13日
    前世は剣帝。今生クズ王子1
    鳩子さんとラブコメ
  • 14日
    鳩子さんとラブコメ2
  • 17日
    鳩子さんとラブコメ3
  • 20日
    鳩子さんとラブコメ4
  • 23日
    世にも美しき数学者たちの日常
  • 25日
    英国カノジョは“らぶゆー”じゃなくてスキと言いたい
  • 31日
    かくりよの宿飯
    現代社会で乙女ゲームの悪役令嬢をするのはちょっと大変3

9月

10月

  • 2日
    VTuberなんだが配信切り忘れたら伝説になってた2

週記(2021/10/11-2021/10/17)

10/11(月)

先週はかなり久しぶり(あるいは初めて?)に、日付が変わる前に週記を投稿した。その後は人の日記を読んだり、ちょっとコードゴルフをして、布団に入った。新しく1作ハーメルンを開いて読もうとしたが眠気には勝てず、いつの間にか寝落ちしていたらしい。直前まで意識を保っていて、寝る前には就寝報告のツイートをするぞと心に決めていたのに、本当に一瞬で意識を落としたらしい。

Chromeの履歴からは、午前2時過ぎに寝落ちしたことが分かった。

午前8時頃目を覚ます。どう考えても睡眠時間は足りていないのだからすぐ眠れば良かったのに、昨日読み始めたハーメルンを開いてしまった。そしてそのまま、なんと午後0時半まで延々読み続けていたようだ。1話当たりの文字数こそ少ないものの、実に150話近くを読み進めた。眠気が耐え難くなってきたこと、一方夕方からインターン先の定例会があることを鑑み、この時間には寝ておかなければならないだろうということで、頑張ってハーメルンを切り上げて寝た。

次に、午後3時半に起床。午後2時から30分おきに目覚ましをかけていたはずだが、眠すぎて結局この時間まで起きられなかった。先週はインターンの進捗を全く生やせていないため、今日の定例会の前に少しでも進めておこうと思ったが、すべてが無に帰した。仕方ないので内容がない進捗報告のスライドを作った。それを発表して、特に何も言われることなく終了。

定例会やそれに付随する諸々が終了して、そこで話した内容からちょっと業務モチベが上がったのだが、ハーメルンの前に人は無力。また開いて先ほどの続きから読み始めた。午後9時から2時間読んで、途中でうっかり布団に移動したのがまずかったのか、また寝てしまった。

午前1時起床。atgolferの更新を見てしばらく頑張っていたが、どれも縮められなかった。またハーメルンの続きを読み進める。パソコンの前と布団を往復しつつ、なんと午前7時半までかけて現在の最新話まで一気読みしてしまった。

syosetu.org

「俺は竈の女神様」。原作が「ダンジョンに出会いを求めるのは間違っているだろうか」というまだ触れたことのない作品でちょっと敬遠していたのだが、ちょうどダンまちが始まるあたりでエタっているということで、読んでみると前半分はほとんどオリジナルだった。後半はクロスオーバーが主軸だが、それも知っている作品が多く、問題なく読めた。最初はクロスオーバーだと気づいておらず、ダンまちの二次創作だと言っているのに東方古代スタートが始まりそうになったときはびっくりしたものだ。

内容は非常に面白い。少し前にハーメルンの捜索掲示板を漁っていた時期があったが、その頃「上位存在」みたいなワードの捜索に頻繁に登場していた作品で、その名に恥じぬ立派な上位存在っぷりであった。ただ人の発展を見守っているかというとあんまりそんな感じはせず、同じく上位存在たちとワイワイしていた、という印象。もちろん信仰を集めたり畏敬されたりという描写はあったものの、メインではなかった。

しかし、Fate/系の話はどこにでも出てくるものだ。他の作品でも、何の脈絡もなく「作品キャラがサーヴァント化したら」みたいな文脈で謎の展開が挿入されることがあって、そのたびにほとんど知識のない自分は読み飛ばし気味になっていたのだった。しかし、しょうがないのかもしれない。ゲームもプレイしないしアニメも漫画も見ない自分であってさえ、主にはTwitterで流れてくる絵経由で、伝説上の人物たちのビジュアルをFate/系列のもので固定しつつある。影響力が大きすぎるのだ。

エゴサーチをしていたら、去年のTCO Regionalで僕がACRushと1対1を行い、勝利したことについて言及している中国語の投稿を発見した。競プロ歴10年以上のACRushに対して僕のことは「后浪」、検索すると「新人」のような言葉で表現されていて、むず痒い気持ちになった。まだICPCも現役であるのだから、心だけでも若くあらねばならない。

zhuanlan.zhihu.com

なんとなく興が乗ったので、インターンの業務に手を付けることにした。とりあえず1つモデルを実装してみる。本当はそれくらいで切り上げるつもりだったのだが、思ったよりうまくいったし、学習自体もデータ数を絞ることで短いスパンで試せるので楽しくなって、昼過ぎまで延々コーディングしていた。今日は1on1の予定があったわけではなかったのだが、無理を言って昼から急に予定を入れてもらい、今日コーディングしていた成果を報告した。またいくつか疑問点を解消したり、自分の認識の正しさを確かめたりした後、次に進めることを決めて終了。

学習を進めればランダム値の具合によらず一定の結果を出すものだと思っていたが、うっかり同じプログラムを何回も回してしまうことがあって、その結果が思ったより異なっていたので、モデルの性能を評価するために乱数のシード値などを固定することにした。randomnp.randomtorchのシード値を設定し、torch.backends.cudnn.deterministicTrueに設定することで結果が一致したモデルと、それでもなお一致しなかったモデルがある。後者はライブラリを呼び出しているだけなので、その中で何かやっているのだろうか。

日記を書いてから布団に入り、ハーメルンを開いたが、すぐに寝落ちしてしまった。午後4時だった。

10/12(火)

午後9時半起床。またしばらくハーメルンを読んでいたものの、その作品は序盤で読むのを止めてしまった。

ハリーポッター二次創作だったが、どうやら連作のクロスオーバーの一部らしく、主人公が別作品由来で、しかもそこからいくつもの二次創作を経てチート能力を身に着けてきた……という設定らしい。こういうのも最初から読んでいけば受け入れられないことはないだろうが、見た感じ僕の知らない作品ばかり渡り歩いているようで、読む気にはならなかった。さらにチート能力を振りかざして原作キャラをおちょくっているのもあまり気に入らなかった。

食事して午後11時半からCodeChef Starters 15 div.2……と思ったら15分こどふぉった。

https://www.codechef.com/START15B

全完して優勝した。1766→1969(+203)。div.2を抜けるにはあと1回コンテストに参加する必要があるようだ。

Aはよい。Bは109以下の数を2000回素因数分解する必要があったので、念のため\sqrt{10^9}以下の素数を求めておいた。3500個程度しかないらしいので、余裕で通る。冷静になると毎回\sqrt{10^9}まで見ても間に合いそうだ。Cは上位桁から貪欲。

Dは面白かった。f(R)-f(L-1)として答えを求めることを考える。下の桁を担当する値を決めると、上の桁として対応させられる値の上限が決まるので、これをソートして尺取り。実際は尺取りでなくても二分探索で通ったようだ。Eは自明、Fは面倒な木dp。Fの遷移を書くのに少し手間取り、これでは優勝できない!と焦っていたが、ふたを開けてみると僕が全完した時点では5完すら他にいなかったようだ。div.2に限らなければ、unratedで参加した中の優勝者は僕より先に全完している。

div.3用の問題を含めて全部解いても1時間もかからなかったが、そのあとTwitterを見たり順位表を眺めてニヨニヨしたりして、結局さらに1時間くらいを無駄にした。

火曜日5限の講義の課題をこなす。Python積分値をできるだけ正確に数値計算せよというものだった。提出方法が面白くて、すでにGoogle Colabと連携された.ipynbファイルが用意されており、それを開いて編集するらしい。Google Classroomを使っていてこそのシームレスさという感じがする。数値計算については、講義スライドにDE法というのが載っていたので、それを適当に書いておけばよさそう。

DE法は実は初めて聞いたが、なかなか興味深かった。幅が有限の区間を無限の区間に置き換えていると思ったが、そもそも幅が有限だからといって結局内部の点は無限個あるのか。また無限の区間であっても、端のほうの重要度をうまいことほぼゼロにしているのも面白い。数式としてみればその理屈もわからないことはないが、実際に計算して精度が上がるのは結構びっくり。

また布団に入って少しハーメルンを読もうとしたが、眠気が強い。午前4時半就寝。

10/13(水)

午前8時前に起床。夢うつつながら、頭皮のかゆみに耐えかねて頭をかきむしった記憶がある。実際枕が毛だらけになっていたので、手で払い落し、いまだ気になるかゆみを抑えるべくシャワーを浴びた。

火曜日の昼間1on1が終わってから(つまり日記では月曜日)回していた学習の途中経過、具体的にはLossの変化をグラフにした。こういうちょっとした作業もやる気が出ないと全然手を付けられない。しかしグラフにしてみてみるとなかなか綺麗な曲線だったので、報われた感じがした。

しばらくパソコンを触ってから布団に戻る。寝ようとしたが眠れず、スマホをずっと触っていた。途中腹を壊したりして、さすがに夏も終わったのにブランケット1枚で寝るのは無謀だったと反省。そのうち気合を入れて掛布団を引っ張り出しておきたい。そのままハーメルンを読んでいたが、正午あたりにやってきた眠気に身を任せ就寝。

次に目を覚ましたら午後7時になっていた。せっかく朝起きたのでゲーセンにでも行くつもりだったのに思いっきり寝てしまった。まあ今日は天気もあまりよくなかったようだし、その点はセーフか。ちょっと食事してからまた布団でハーメルンを読み続け、午後11時過ぎになって身を起こした。

atgolferにPAST8の問題が流れてきていた。いつの間にかPAST8がAtCoderのトップページに表示されるようになっていたらしい。どうせ表示されないのはただの設定ミスだろうと思って、専用でクロールするような設定は入れなかった。

午後11時35分からCF #748 div.3。全完3位。

Dashboard - Codeforces Round #748 (Div. 3) - Codeforces

Aはよい。Bはちょっとびっくりするが、下2桁を全探索すればよい。正数を探す必要があるので、下2桁が00だったりしたらどうするのか、という気持ちになるが、与えられる数字にleading zeroが存在しないという制約から、00を選んだとしてもその左にちゃんと非ゼロの数字が存在してくれる。Cは、猫がn-1にたどり着く前に穴に入れるネズミの数を数えればよく、これは穴までの距離が短いものから貪欲に取ることで達成できる。最初n-1ではなくnで計算していて、適当に1引いたらサンプルが合って困ったが、ちゃんと自分で納得できて提出した。D1は差のgcd。

D2は答えを全探索する。ある値gが答えになることは、a_i\bmod{g}を集計して\frac n 2個以上が同じであるか?によって判定できる。この判定はmapの代わりに配列を使えばO(n)で可能なので、それを2\times 10^6回行う。\sum n\le 100という制約から変数による剰余の計算を2\times 10^8回行うことになってしまいかなりドキドキしたが、エイヤと出すと780msで通った。Eは葉から多始点bfsかと思ったが、落ちた。冷静になると、トポロジカルソートにおけるキューに入れるタイミングを次数1以下になったときと定めたような計算をする必要があった。Fは桁dp。Gは、'['または']'のあるインデックスを偶奇に分けてカウントし、それらが同じになることがコスト0で正しいかっこ列に変化させられることの必要十分条件。累積和で求まる。

全完した後しばらくTwitterを見ていたはずだが、いつの間にか布団に倒れこんで寝たらしい。Chromeの閲覧履歴によれば、午前1時半に寝落ちしたようだ。その直前に開いていたページはTLに流れてきたブログ記事で、確かに布団に寝ころびながらそれを開いて読み始めた記憶がないでもない。

10/14(木)

意識を取り戻したのは午前6時だった。またスマホを触ってハーメルンを読み続けていた。

午前10時くらいになって、無理やり切り上げて布団から出た。今日はゲームセンターに行く。夕方から1on1があるので、それに向けて今のうちに何らかの進捗を捻り出しておくことにした。ちょっと気合いを入れれば終わるようなタスクを1つ片づけて切り上げ、しばらくパソコンを触ったあと、出かけた。

東北大学川内キャンパスの近くの交差点は、朝から夕方まで歩車分離式になっているが、交差点を斜めに渡るような横断歩道がペイントされていないため、斜め横断は常に不可能である。ほとんど無視されているような規則だが、定期的に警官が交差点に立っており、斜め横断を見るや否や止めて注意するという光景が見られる。大学生活4年目にして初めてこれに引っかかった。これまでは、自分の前を走る人が止められているのを見てギリギリで警官に気づいたりしたが、それでもセーフだったのに。

食事してゲーセン。今日は新しい靴を履いていたのだが、足首の前のほうに余裕がなく、前方に体重をかけてゲームをプレイしていると靴が食い込んで痛かった。東方の新曲については、先週譜面動画を見ながら難しそうだと言っていたが、案の定13の2つはAJが出なかった。

今日アップデートでチュウニズムに追加された新曲の譜面動画を見ていた。13に追加された2つがどちらもかなり強めに感じられる。AJは難しそうだ。

週記(2021/10/04-2021/10/10) - kotatsugameの日記

理論値が1譜面増えた。前回ゲーセンに行ったときに狙っていたもの。

午後4時過ぎにゲーセンを出る。食事でもしようかと思ったが、あまりおなかが空いていなかったのでそのまま帰宅し、シャワーを浴びて午後5時から1on1。前半で進捗を報告した後は、扱っているデータの様子と学習結果を見て次回までの課題を決める。ビジュアライズするのにちょっとしたコードを書く必要があって、すぐ書けるので今書いてお見せします!と自信満々に宣言したはいいものの、設計がすぐに思い浮かばずしばらく手が止まってしまうなど、情けない場面があった。

1on1が終わってからも少しコーディングを続けていたが、学習を回して放置するフェーズに入ったので切り上げた。しばらくYouTubeを見てから布団に入ってしまい、すぐ寝落ち。午後7時半だった。午後8時半に一瞬起きてTLを見たような記録があるが、またすぐ寝たようだ。

10/15(金)

午前2時起床。夢を見た。

またずっとハーメルンを読んでいたが、今日は夕方から院試ゼミのメンバーで飲み会をする予定。午前10時くらいになって、さすがにもう一度寝ないとまずいという気持ちになり、目を閉じてみた。しかし眠れない。結局起きることにして、とりあえず学食に行った。

昨日寝る前に回していた学習が終了していたので、結果をちょっと加工した後、パラメータを弄ってまた学習を回し始めた。この作業は10分もかからないものなので、勤務時間の記録にどう入れたものか悩む。今後学習のための時間が長くなっていったらどうすればいいのだろうか。

僕が本格的に稼働し始めた3週間くらい前から、インターン先のSlackに自分の名前がついた(ほとんど専用の)チャンネルを用意してもらっている。業務の進捗とかはTwitterと同じ感じでそこに投げ入れているが、これは自分の性にかなり合っていると感じる。そういうチャンネルは他の社員の方も持っている。以下の記事のような運用になっているのだろう。

Slackで簡単に「日報」ならぬ「分報」をチームで実現する3ステップ 〜Problemが10分で解決するチャットを作ろう〜 - 株式会社クラフトマンソフトウェア

日記を書いていたが、かなり眠くなってきてしまった。飲み会は午後5時からで今ならまだギリギリ間に合うと信じて、昼寝することにした。睡眠の周期を考えて90分後に起きることにして、午後2時過ぎに横になった。

実際にはこのツイートをした後も布団の上で眠気に耐えようとしばらくクネクネしていた。なんとか身を起こして午後4時過ぎに家を出た。店の位置と地下鉄の駅の位置をあまりよく分かっておらず、歩いたほうが早かったかもしれないところを、うっかり地下鉄に乗ってしまった。せっかくお金を払うのだからと思って2駅ほど乗ってゲーセンの最寄駅まで行ったが、1プレイする時間はなく、そのまま店まで歩いて行った。思ったより遠くて、結局地下鉄1駅分くらいは歩いて戻ったらしい。店はここ↓。

仙台 居酒屋 【佗び助】

店の前につくと他の3人はすでに揃っていて、即座に入店。予約の関係で2時間しかいられなかったが、せり鍋に加えて海鮮サラダ、魚のから揚げ(何の魚だったか忘れた)、馬刺しなどを注文。また日本酒も店のおすすめなどを含めて3種類、それぞれ1合ずつ注文した。院試お疲れ様会ということで少し高めのお店にするべくここが選ばれたが、実際1人4000円くらいで、自費で飲み食いした中ではかなり高いほうだった。

おいしいのだろうとは思うが、味をあまり気にしていなかったためよくわからない。量については腹6分目という感じか。女将が鍋を差配しつつあれこれ話していて、そういうタイプの接客も初めて受けるもので高級感を感じる。話の内容はせり鍋の蘊蓄、来店した有名人、店でやっている落語の寄席、くらいだっただろうか。これも途中から興味を失ってしまった。以上、店についてネガティブな言い方をしてしまったが、しかし4人でお酒を飲みながら話すのは非常に楽しかった。

最初は焼き肉屋に行こうという話で、僕が以前腹痛で救急車を呼んでしまったためちょっとトラウマ……と言ってこの店に変えてもらった経緯がある。多分焼き肉屋のほうが飲み食いしながら話すという目的には合致していたのだろう。またそのうち別のお店に行こうという話になったので、もし焼き肉屋に行った場合はちゃんと肉を焼くこと、生肉をつかむトングを分けることを徹底したい。

飲み足りないので2軒目に行く。以前2週連続で行った、1杯200円のバー。今日も注文の内容をリプライツリーにまとめた。

先週の金曜日にも行ったバーに再度入店した。

週記(2021/02/22-2021/02/28) - kotatsugameの日記

飲みながら今日もまたソートなぞなぞをしていた。QuizKnockの動画から知った人もいてびっくり。競プロer特有の文化かもしれないと心配していたが、問題なく楽しんでもらえたようでよかった。出題されたものは記録をとっていないのであらかた忘れてしまった。

店を出て別れ、ゲーセンに駆け込んで閉店まで1時間弱プレイした。これまでの感覚から言えばそこまで酔っているわけでもなかったようだったが、それでも本調子でないことは確かで、ただただスコアが出なかった。閉店後地下鉄の駅に向かって歩いているとマックが見えてきて、なんとなく入店してしまった。ポテトのLとコーラのMを頼んだが、お酒で腹を下し気味だったので、コーラのほうはSサイズでよかった。ポテトをつまみつつしばらくハーメルンを読んでいた。マックのトイレを借りるかと思ったが、明らかに泥酔している人が出てきたため敬遠して帰宅。終電もなくなっていたため、延々歩いて帰ってきた。

シャワーを浴びて布団に入り、すぐ寝た。午前2時前だった。

10/16(土)

午前9時前に目を覚まし、またハーメルンを読んでいた。今日は午後2時まで読んで、ARCに備えてまた寝た。午後4時くらいに生協の弁当配達があって一瞬起きたが、この時はまたすぐ寝ることに成功した。

午後8時起床。atgolferを確認すると、マラソンのコンテストで同じ問題3問×本選とオープンの合計6問が一気に更新されていてひっくり返った。3問あるのはいいけども、なぜ問題idを変えたのか……。どうしようもないので眺めてしみじみしつつ、午後9時からARC128に出た。

Daiwa Securities Co. Ltd. Programming Contest 2021(AtCoder Regular Contest 128) - AtCoder

3完遅めで何もかもが崩壊した。最近ヤバい。

Aから難しい。A_iのうち最も値が大きいものを考えると、その右(つまりそれ以降)にまだ交換しない日があるなら、そのうちA_iが最小の日と組みにして交換することにしても損しない。以降は選んだ組を無視して同じことを繰り返すが、銀に交換→金に交換というステップの繰り返しを崩さないように最小値を検索する範囲を制限して行う。選んだ最大値より最小値のほうが大きくなったら切り上げる。Bはつい最近インターン先の勉強会でほぼ同じ問題が扱われており、難なく解けた。といってもA問題をACしてからの時間を見る限りFAは僕より1分以上速いらしく、頭が回っていないなあという感じ。

……このツイートを引用するかどうかは迷ったのだが、多分ちょっと調べるとわかる情報だろう。

C問題は難しかった。d_i=x_i-x_{i-1}などと置いて書き換えてみても、あまり見通しは良くならない。しばらく唸っていたがどうしようもないので、元の問題に戻って解の形を考えてみると、どうにもd_i\ne 0なるiは少ないんじゃないかという気持ちになる。N\le 5000ということもあり、d_i\ne 0なるiを2つ決め打って計算するO(N^2)のコードを書いたら通ってしまった。誰かのツイートで見た言葉だが、問題を解釈して一般的な問題に落とし込むと元の問題の構造が失われてしまうことがある。今回はその一例だったかもしれない。

Dは解けなかった。隣接する要素が等しい位置で数列を区切り、それぞれ解くことにして、解き方はdp、更新先が区間になるだろうというところまで考えた。その更新の区間を求めるコードが全然違っていたようで、半分くらいのケースで落ちるようなコードしか書けなかった。スタート地点からある程度先「まで」の区間に対して更新するだろうと考えていたが、TLを見る感じある程度先「以降」の区間に対して更新するようだ。なんてこった。

コードゴルフをする。AはOctaveで、まず数列のdiffを取り、それが0より大かどうかの列を作ってまたdiffを取るようなアルゴリズムで解ける。BはRuby。高度な機能を持ち出して全探索するより、ソートして場合分けを並べたほうが短くなってびっくりした。Cは線形計画問題なのでOctaveのglpkで解けるようだ。

夜中CodeChefのSnackdownにレジってQualの問題を解いた。来週火曜日までで、週記を投稿する予定の日にまだ終わっていないため、ここでは何も言わない。

最近熱心に読んでいたハーメルンを読了。「阿礼狂いに生まれた少年のお話」。

syosetu.org

非っ常~~~に良かった。設定についてもオリキャラと原作キャラの繋がりがいろいろあって楽しめたし、前半分のほうは主人公の強さも印象的だったが、後に行くにつれて、そうした表面的な面白さの奥に潜む主人公と周囲の人妖の関わりの物語がだんだん現れてきたように感じられた。特に阿求の章に入ってからは、すぐそこまで迫った主人公の寿命があり、その中で友誼を結んだ妖怪にとっての死別のとらえ方だったり、人里の先立った人・残される人とのやり取りだったりが感傷的に描かれていた。ラストで主人公が亡くなり終了かと思ったら、幕間という形で亡くなった直後の幻想郷の様子が描かれ、僕はそういうのに弱いので泣いてしまった。

朝方はずっとコードゴルフをしていた。今日起きた時にatgolferに流れてきていた更新は取り返せなかったが、ちょっと前のコードをずっとタブに開いていて、改めて考えていたら少し縮めることができた。その後日記を書いたら午前11時だったので、布団に入る。今まで夏用のブランケット1枚を引っ被って寝ていたが、さすがに寒くなってきたので、秋用の掛け布団を出すことにした。布団カバーをかぶせてみると微妙にサイズが合っていないように見えるので、もしかしたら冬用の布団のカバーを出してしまったのかもしれないが、今更戻すのも面倒。

布団に入って昼過ぎまでハーメルンを読んでいた。TLを見て、日曜日の昼からJOI一次予選(第2回)があることを知った。第1回は大体1月前に開催されたが、その時は予選が終わって1時間もしないうちにAtCoderに過去問が公開されて、起きたころには自明な最短はすでに取られていたのだった。

今日の昼頃行われたJOI一次予選の問題が2時間前に公開されていてびっくりした。

週記(2021/09/13-2021/09/19) - kotatsugameの日記

今回はそんな失敗をしないようにしたい、ということでもうすぐにでも寝て、午後4時くらいに起きることにした。午後1時就寝。

10/17(日)

午後4時起床。まだJOIの問題はAtCoderで公開されていない。非常に眠いので寝たい気持ちが強いが、そうしている間に公開されたら悔しいので、頑張って起きていることにした。この時点では、公開されたらすぐ取り掛かって、ABCまでまたしばらく寝ようと考えていた。

atgolferの更新を見ながらコードゴルフしていたが、一向に公開される気配がない。コードゴルフでは、gets.bytes$<.bytesに置き換えられることに気づき、検索するとこれで縮むコードが結構あったので拾ったりしていた。午後7時あたりでいったん切り上げて日記を書き、午後9時からはABC223に出た。実は今日は午後8時からCFでcombinedがあったのだが、ABCと被っていたので見送ってしまった。

AtCoder Beginner Contest 223 - AtCoder

A問題はちょっとひっかけ気味。0円に対してはNoと答える必要がある。逆にこの設定があると、正規表現/00/にマッチすることがYesと答える場合の必要十分条件となってくれる。最初は/00$/でないとダメだと思っていたが、入力される値の最大値が1000なので/00/でよい。B問題はRubyで書いた。

CからはC++。距離を二分探索して、左右からそれぞれかかる時間の差が0になる点を見つけた。Dはトポロジカルソート。Eは↓の問題からの類推で試すべき敷き詰め方のパターンを予測し、対称性からループなどでまとめて書いたらかなりスッキリした。Fは遅延セグメント木で括弧列を±1に直した累積和を持つ。Gは木の最大マッチングが葉から貪欲でよいことを元に全方位木dp。HはDisjoint Sparse Tableを貼ったがマージに602回くらいの計算が必要で、そこをどうしても落とせなかった。

atcoder.jp

もう結構な期間ゆっくり実況を出していないが、一応AtCoderのコンテストに参加するときは画面キャプチャを撮っている。撮っているつもりだったのだが、最近3回分でサブモニタがキャプチャされているのに気づき、非常に残念な気持ちになった。以前同じ現象が発生して、ちゃんと直したはずだったのだが……。パソコンを再起動すると元に戻ってしまうとか、そういうことだろうか。以前とは使っているケーブルもモニタも変わっていないはずなのだが、抜き差しすることに副作用があるのか?

ふと思い立って画面キャプチャのテストをしてみたところ、これまで真ん中のメイン画面をキャプチャできていたのが、いつの間にか左端の画面をキャプチャするようになってしまっていた。

週記(2021/09/13-2021/09/19) - kotatsugameの日記

コードゴルフ。Aはsedでよい。BはRubyで頑張っていたが、コンテストが終わってみるとVim 25Bがあって何も勝てないという気持ちに。Cは2つの火がぶつかる時間が\frac 1 2\sum \frac{A_i}{B_i}と求まることを解説を読んで知った。これを使ってdcで頑張って現在52B。符号を弄ったり式変形を繰り返した結果、なぜこれで答えが出るのか自分でもよくわからないコードになった。

DはPythonheapqを使う問題に見えていたが、提出を眺めているとRubybsearch_indexinsertを使ったコードがギリギリ通っているのを見つけた。実際書いてみると、たまにTLEするものの数回出せば確実に通っていく。そのコードを縮めることにした。連想配列を使うような書き換えをしているとC++脳ではlogがついて遅そうに見えるが、Rubyのそれはhash mapなので思ったより速かった。

Eはパターンをまとめて頑張る。.permutation.any?を3段に重ねるようなコードを書いた。どの長方形を固定するか、縦横どちらに固定するか、残りの2つを縦横どう置くか。コードを文字列のjoinで作ってevalしていたが、入力読み込みのときに改行がついてくるのに気づかず不要なセミコロンを入れており1B負けてしまった。あとは手付かず。

最短コードが1700問になった。

今日が終わってしまったが、まだJOIの問題は公開されていない。せっかく頑張って起きたのに……という気持ちもあるが、今週は生活リズムを崩し続けた一週間だったため、最後にこのような形で多少整ったのは不幸中の幸いか。せっかくなので空が白み始める前に寝たいものだ。

週記(2021/10/04-2021/10/10)

10/04(月)

正午起床。寝ている間に大学院科目の先行履修の書類が受理されたとのメールが来ていた。一安心。

手癖でYouTubeを開くと、チュウニズム14新曲のAJ動画が投稿されていた。2人目が出たらしい。

www.youtube.com

シャワーを浴びて学食に行く。先週金曜日から秋学期が始まったということで生協の営業時間も更新されており、学食の昼の部は30分伸びて午後2時まで営業しているので、かなり余裕があった。帰ってきてから1時間くらいかけて溜めていた分の日記を書き、投稿した。

それから夕方のインターン先の定例会までは、それに向けた作業をしていた。とりあえず進捗報告用のスライドを1ページ用意する。さらに、先週Kaggleのチームを組んでから何もしていないのに罪悪感を覚えるので、とりあえずコードを手元で動かしたりしてみていた。入力データを絞ってちょっと実行するだけでも結構時間がかかって辛い。

定例会は今週も普通に終了。続いてKaggleチームのミーティングも行われ、そこで少しばかり質問した結果、どんなコードのどこを弄ればよいのかが分かった。一般に特徴量を増やす関数としてadd_featuresがどこかで定義されており、ここでオレオレ特徴量を入れて学習を回しスコアを見るのだとばかり思っていたが、それももちろん重要な一方で、モデルをいろいろ弄ってみるのも、最後にチーム全員のモデルをアンサンブルするため必要なステップらしい。魔法の特徴量は見つかったら根本的にスコアに影響を与えるものの、そう簡単に見つかるわけがないから、チームに貢献したいならモデルのほうでいろいろ試してみるべきかもしれない。

機械学習Pythonコードを手元でいろいろ変えつつ動かすのは、いちいち先頭から実行しなおす手間がかかってさすがに耐えられないため、ローカルにJupyterを入れた。試しに起動してみるとかなりいい感じ。大学のPythonを扱う講義ではいっつもGoogle Colaboratoryを使わされるが、似たようなものがローカルで動いていると感動を覚える。それでもらってきた.ipynbファイルを開き、自分の環境に合わせて少し書き直した上で走らせてみた。依然として実行に時間がかかるのが嫌なので、とりあえずデータ量を絞っていたところ、生成されるべきファイルがないというエラーが出て困っていたが、それもちょっとした手直しで解決して、一通りは動くようになった。

と、かなり良い感じになってきたがここでいったん放置して、4年ゼミのスライド準備を始めた。教科書のキリの良いところまで行間を埋めることに成功したので、Beamerを使い体裁を整えながら打ち込んでいく。あまりに久しぶりすぎていろいろ忘れてしまっていたが、これまで用意してきたTeXファイルを見ながら書いていった。5時間くらいかけて、とりあえず読んでおいた部分のスライドが完成。教科書のページ数としても、スライドの枚数としても、発表のためにはこの2倍弱の分量が必要だろう。しかし教科書の次の部分は章末の演習問題である。これまでのゼミでは、演習問題はみんな無視してきたが、そうはいってもとりあえず目を通しておくくらいはするべきだろう。そうして読んで、やっぱりやらなくていいかな……という気持ちになったので、次の章に入ることにした。次の章の内容は幾分簡単そうに見えるので、どうにでもなるだろうと思って今日はここで切り上げた。

明日は1on1の予定だが、前回金曜日から一切業務に手を付けていない。学業に専念している感じなので仕方ない、明日は正直に何もやっていませんと言うことにした。インターン先は良い会社なので、学業を優先させてくれるのだが、そうはいっても何も言わず急に業務を放り出すのはよくないだろう。これからは事前に、この時期は学業で忙しくしています、ということを報告しておきたい。

14AJの手元がまた1本投稿されていた。結構前からずっと追っているチャンネル。99AJでもうなんか全てがすごい。

www.youtube.com

今日は夕方かなり眠気があったつもりだったが、それでもいつの間にか午前4時過ぎまで起きてしまっていた。夜更かしが本当に常態化しておりまずい。とりあえず完全に朝になる前に……と布団に潜り込み、午前5時過ぎ就寝。

10/05(火)

午前11時前に目を覚ます。TLをちょっと眺めていたら眠れなくなって困っていたが、気合を入れると再度意識を落とすことに成功した。確かそれが午後1時過ぎのことだったと思う。

午後2時半、1on1前の目覚ましで起床。起き抜けはかなり頭がボーッとして身動きが取れなかった。途中分割されているものの、合計の睡眠時間だけ見れば結構寝ているので、深い睡眠から無理やり起きてしまったのだろうか。ちょっと怖い夢を見たが、すでに細部は失われていた。

1on1は10分で終了。次回はゼミが終わった翌日の金曜日にお願いした。さすがに1日くらいあれば何か報告できる進捗が産まれてくれるだろう。

今日の5限に講義を1つ入れたはず、と思ってClassroomを確認したところ、初回である今週は課題なしで、スライドや動画を見るだけ。「AMATERAS RAY」(なかなかかっこいい名前だ)というサービスを使って適当な目的変数を予測してみるという内容で、プログラミングは一切行わなかった。僕らのような素人がGUIでポチポチやっている裏では、サービス提供元の作り上げたごっついモデルが動いているんだろうなあと考えていた。今回の講義で出てきた言葉から自分なりの「キーワード」を探して回答せよという指示だけあったので、「説明変数」と答えておいた。

Service Amateras

大学生協に寄って買い物をしてから、街中に出てゲーセンに行く。その前に腹ごしらえをしようと思い、一閃閣というラーメン屋に行こうとした。この店は仙台に2店舗存在する。自転車を停めた場所がその2店舗からちょうど等距離にあるように思えたので、これまで行ったことのない店舗のほうに行こうと思い、しばらく歩いていたところ、以前この辺りを通りかかったときは閉まっていた「昭文堂書店」という本屋が営業しているのを見つけ、ふらふらと吸い寄せられてしまった。

棚いっぱいに古びた大きな専門書が詰め込まれている、絵に描いたような古本屋さんだった。頭の白くなったおじいさんが店番をしていて、客は僕一人。人文学の本で埋まった棚を眺めつつ、何も買わずに出るのもアレだけど、ここにある本を買ってもなあ……と思っていたが、別の棚に行ってみるとそっちは完全に理系だった。店のちょうど真ん中を境に、いわゆる文系向けの本と理系向けの本が分けられていたようだ。並んだブルーバックスの背表紙にMS-DOSとかC言語とか書いてあるのを見て、これはもう古典だな、と思うなどしていた。数学に関する本やコンピュータに関する本を一通り確認して、「プログラマの数学」という本を購入した。ホスフィンが売り払った本である可能性があるらしい。世間が狭すぎる。

うっかり30分くらい古本屋に吸い込まれていた。出てから改めてラーメン屋を探すと、目の前に建っていたものの、閉まっていた。慌ててホームページを確認すると、どうやら平日は昼間しかやっていないらしい。そんな……と思いつつ、完全に一閃閣の気分になっていたので、一番町まで延々歩いてもう1店舗のほうに向かった。そちらは問題なく営業しており、食事にありつけた。

ゲーセン。新曲の13+、「Love & Justice」を何回かプレイしていたが、SSSは不可能であるという結論に至って放り出した。難しいところは全部8分全押しで通りそうだが、全然安定しなかった。あとは12+のAJを6個99AJに更新し、理論値を1曲出し、13AJを1個出し、さらにもう1曲理論値を狙ったが出せずに終了。

最後のトラックで「TiamaT:F minor」をプレイしたところ、1500点伸びて14では初めてSS+に乗った。序盤の鍵盤を適当に擦って大量失点しているので、ちゃんと運指を考えたらワンチャンあるのかもしれない。

ざるそばを食べて帰宅。帰る途中、大通りから分岐した脇道の横断歩道を一時停止なしで渡ろうとしてしまい、ちょうど横から車が来ており、お互い急ブレーキをかけてギリギリ接触せずに済んだ。なぜ気づかなかったのかなど反省点が多いはずだが、そのときちょうどぼんやりと考え事をしていて記憶が定かではない。

帰宅してちょっとコードゴルフをした後、昨日の分と合わせて日記を書いた。今日は結局ゼミ準備をしなかった。午前4時就寝。

10/06(水)

午後2時頃に目を覚まし、atgolferの更新を見て縮まないかしばらく考えていた。なんとなく縮みそうな気がしたのでいったんパソコンの前に座ったが、しばらく試行錯誤して、途中で別の問題が縮んだりしつつ、元の問題はやはりダメだったことが分かったので、また布団に戻った。

tatyamさんの、PAST8のバチャをツイキャスでするというツイートが流れてきた。慌ててAtCoderのトップページを確認するも、特に表示はされていない。ツイキャスを見ても画面が小さくよくわからなかったので、別の問題を解いているのだろうと勝手に納得して閉じた。しかし、他にもPAST8のバチャに関するツイートをいくつか目にして、試しに以下のURL(過去のPASTから推測できた)を直接打ち込んでみたところ、見事にPAST8のコンテストページが開けてしまった。

https://atcoder.jp/contests/past202109-open

慌ててパソコンの前に戻り、解き始めた。Aのdc 11Bはさすがに自明すぎて取られていた。Bはそもそも負け。Cはdc 22Bを書いたが、この日の夜遅くに21Bに更新された。DはPerl 53B。

Eは自分では綺麗に書けなかったが、Rubyのかなり上手いコードが夕方提出され、そのあまりの美しさにひっくり返っていた。

atcoder.jp

Fは結構頑張ってRuby 78B。GはRubyで二分探索するだけで90B。HはC++で適当に書いて、IはCython。そこから先の問題はそう簡単に縮まなさそうなので、急いで解く必要があったのもこれくらいか。午後6時くらいに一段落したと感じたので学食に行く準備をしたが、やっぱり気になってさらにコードゴルフしている間に学食が閉店してしまった。

PAST8がいつ公開されたのか提出を調べてみると、なんと日付が変わったあたりの提出が存在したことが分かった。なぜAtCoderのトップページに出ていないのか。腹が立ったので愚痴をツイートした。

しばらく別のコードゴルフをしていた。今日の起き抜けに縮んだ問題がさらに大幅に縮められていたので、それを取り返す。しばらく格闘した後にまたPAST8に戻ると、いろいろ縮められていた。先に述べたE問題のコードが提出されているのを見つけたのも確かこの辺りだったはず。他にI問題も縮められていた。I問題に関しては方針を大きく切り替え、先に3倍を繰り返した要素たちの列を作っておいて、全体をソートしてから特定の位置の値を出力することで大きく縮めることに成功した。

さらに問題を解く。JKはC++、LもC++で書いたが、二分探索の中でさらにBITを使ったらTLEしてしまった。logを2つつけたらTLEした、のようなツイートをどこかで見たので、ああこの問題だったのだなと思った。冷静になるとソートして尺取りすれば線形時間で判定が行えるので、それで通した。解説では、尺取りは上端と下端を持つというようなことが書かれているが、実際にはどちらかを今見ているインデックスに合わせておけば区間がそれぞれちょうど一回カウントされるようになり、後から半分にする必要もないし定数倍も半分になってくれる。コードゴルフしようとしたが、RubyではなくCrystalでないと通らないようだったし、そちらも謎のREが出てしまったので放置。

午後9時過ぎ、さすがに明日のゼミ準備がまずい気がしてきたので、そちらに取り掛かった。途中集中力を失ってコードゴルフに戻ったりTLを眺めたりしていたが、午前3時半くらいになって一応の完成を見た。月曜日に進めていた分に比べて、今日やった箇所は章が変わって初めのほうということもあり、かなり簡単め。それでも、教科書で直ちにわかるとか書かれている部分が微妙に怪しく感じられたので、結構丁寧に(あるいはねっとりと)証明を書いた。

ICPCのアカウント設定を済ませる。Activateが必要で最初ログインに失敗したときはちょっとドキッとしたが、問題なく完了した。アカウントに登録する情報について、去年急に「Number of Full-Time STEM Semesters Completed」という項目が増えて困惑したことを覚えている。去年は以下のような理由で5を記入し、そのことを日記にも書いたのだった。

STEMとはScience、Technology、Engineering、Mathematicsのことで、それに関連する学科を指しているのか?とりあえず、僕は数学科で2年半、つまり5セメスター過ごしてきたため、5と書いておいた。

週記(2020/10/12-2020/10/18) - kotatsugameの日記

今年はICPC横浜大会公式ページ最下部のQ&Aにおいて、この項目が初期値0のままでよいと明言されているため、それに合わせておいた。未だに「Number of Full-Time STEM Semesters Completed」で日本語サイトを検索すると僕の上の週記がトップに表示されるため、迷い込んでしまう人のためにそちらにも追記しておこう。

アカウント登録 | ICPC 2021 Asia Yokohama Regional

明日に備えて寝ようと思ったが、ふと思い立って、以前より温めていた短編小説のプロットを書き始めた。核となる競プロ関連のネタはしばらく前に何となく考えていて、加えて最近pixiv小説でテーマが合致した執筆応援プロジェクトとやらが行われているのを知り、以来数日なんとなく想像をたくましくしていたところ、ここにきて急にいろんなシーンが思い浮かんできたので、それを忘れないようメモしようというわけだ。大まかな流れを書いておけば、その適切な位置にシーンをメモ書きの形で挿入し、保存しておくことができる。

しかし、思い浮かんだもののうち覚えていたシーンだけ付け足しつつ書き上げてみると、すでにいい具合のボリュームがある気がする。これをしばらく寝かせて新たに思いついたシーンを挿入するのもよいが、それよりも今は、これを実際の短編小説として出力してみたいという気持ちが大きい。あまりに楽しみすぎて明日早いことを忘れ、4時間かけて完成させてしまった。一読して誤植などはなさそうに見えたため、そのままpixiv小説に投稿した。約8000文字。ちゃんと起承転結を意識したつもりで、12が起、345が承、6が転、7が結だと考えている。

www.pixiv.net

せっかくの日記なので、後書きっぽいことをここに書いておこう。以下の文章には上の短編小説のネタバレが含まれる。

先に話した核となるネタはもちろん、フロアの電気を全部消すスイッチの組み合わせを求める問題である。しかしそこからどういう話にするのかは非常に難しかった。導入はまあどんなものでもよいだろうけど、消した後はどうなるのか。あるいは消す過程を詳細に記述することも考えたが、これもどうもうまくいかない。貪欲などしていてはダメだから、結局基底を取るしかないのである。そこで、電気を全部消したときにビルの隠された空間を知る、という展開を思いついた。すると今度は現実味がなくなった。単純に壁が動いてお宝が……よりはリアルにありそうなことを描きたい。というわけで、全部消したはずの電気がついているという流れで発見されることにした。最初に「奥まったところから光が漏れ出ている」という気づき方を考えたが、ビルのフロア丸々使った1室という舞台に奥まったところを無理なく設定できなかったので没になり、外から見て気づくという流れになるようにした。

ここまで、つまりビルの電気を消し、外から見て隠し部屋に気づくという流れが、考えていたプロットの根幹である。あとは適当に考えたシーンを書き加えただけであり、それをどうやって思いついたかについてはほとんど覚えていない。が、「ビルの電気がついたり消えたりしているのを見て」のくだりはなかなかお気に入りである。実際のところ、フロアの光量が激しく増減しているのを見てもそういう表現にはなると思うが、多少は許してくれよな!という感じだ。相変わらずラストをどうするか決められなかったので、最初はリドルストーリーにするつもりだったが、さすがにそれは放り投げすぎだろうということで、ちょっとばかりショッキングな描写を入れてお茶を濁した。あとは伏線になるように適当に言葉を散りばめて完成。友人の感想では伏線が弱く感じたという話だったが、まあ初めて書いた小説にしては良いだろうと自画自賛しておく。

長さ8000文字は思ったより短く、もうちょっと余計な描写を入れてもよかったかも、と思わないでもない。1、2のあたりではまだ周囲の描写を入れたり、地の文と会話文の量に気を配っていたのが、だんだん文章を書くのに夢中になっていってそういう配慮は姿を消し、自分の書いたプロットに忠実に、必要なことしか書かなくなってしまった。また、自分なりの伏線回収の部分に圏点を打ったのだが、「言う事全部重要おばさん」が思い浮かんでダメだった。

投稿してすぐ、朝にも関わらず数件のいいねやRTが来て嬉しくなった。そのままTLを見ていたい衝動に駆られるが、4時間後にはゼミが開始してしまう。午前9時半就寝。

10/07(木)

午後0時半起床。眠すぎて動けないが無理やりスマホを睨みつけて眠らないようにする。何とか布団を這い出し、食事してゼミに備える。

ゼミ準備としては、スライドを元に口頭で説明したいことを紙にまとめておくのがよいのだった。幸い今日の発表は2番手になったので、1番手が発表している間に見直しを進める。すると証明が壊れていることに気づいてしまったが、教科書の参考文献を試しに検索してみると元論文が見つかったので、それを見て修正。何とか間に合ったが、土壇場の変更をスライドにちゃんと反映しきれていなかったのが悔しいところ。発表している最中に修正点をいくつか見つけたので、逐一メモを取って後から直しておいた。今回もスライドをここに載せておこう。

Apostol_Chapter4_4.10-4.11_Chapter5_5.1-5.2.pdf - Google ドライブ

発表内容としては特に問題なし、だったと思う。記号の読みとかスライドの記法とか、そういう話はいくつかされた。正直次回まで覚えていられるかは……謎。メモとしてここに書き残しておこう。句読点を.と,に置換していたが、これは別に半角でもよく、教科書に合わせて数式にピリオドを付けたりするならば半角のほうが良い。また\hat{a}は「エーハット」と読む。あと、これは僕の宗教を許容されたのだが、量化子付きの命題を書く際に\forall x\in A.\;\varphi(x)とピリオドを付けて書く、一部の数学基礎論で見られる記法についても話題に上がった。

ゼミが終わってから、今日アップデートでチュウニズムに追加された新曲の譜面動画を見ていた。13に追加された2つがどちらもかなり強めに感じられる。AJは難しそうだ。

ゼミ中に部屋のチャイムを鳴らされたが、その時は数十分以上後にまた来てくれと言ってお引き取り願った。夜ごろまた来る、というようなことを言っていたが、午後5時くらいに来たので対応。電力自由化を利用して電力料金を下げないかという話だった。面倒なので断るタイミングを伺いつつ、ついついごみ箱から電力料金のはがきを掘り出して見せたりしていたのだが、その場で入力させられそうになったので直截的に「その気はない」と言った。するとすんなり引き下がってくれたのだが、最後少しの会話で僕が親からの仕送りに頼って暮らしていることを明かすと、そういう人を勧誘してはならない決まりなのだと言う。よくわからない決まりだが、お互いにとって意味のない十数分だったことが明らかになり、ちょっと申し訳ない気分になった。

夕方はTLに人が多いことが期待されるので、昨日投稿した小説のツイートをセルフRT。目論見通り新たに数人がいいねやRTをしてくれて嬉しい。

昨日のPAST8-I問題が、昼頃さらに縮められていたようだ。これはもう、いったい何をしていたのかというレベルの典型の見落とし。非常に悔しい気持ちになった。

今日こそ学食に行く。今日初めてのまともな食事ということで、入るだろうと楽観視して丼の小にラーメンの大を合わせたのだが、全然食べきれなかった。なんとか丼とラーメンの麺だけは腹に収めたが、トッピングのから揚げは見るだけで嫌気がさしてしまったので、残した。うっかり癖で大サイズを注文したのが失敗だった……。少し膨らんだ腹を抱えてえっちらおっちら帰宅した。

しばらくTLを眺めていたが、急激な眠気に襲われて午後8時半くらいにベッドに倒れこみ、そのまま日付が変わったころまで寝ていた。

起きてからしばらくは、以前に読んだなろうの読み返しをしていた。印象深いシーンを思い出して探していたのだが、2500話近くあるとタイトルを眺めて思い出すにも結構限界がある。ずっと遡っていきつつ他のシーンも拾い読みしていたが、実は求めていた話は結構最近のものだったらしい。そういうことを、途中TLを眺めたりしつつ午前5時までやっていた。

今週日曜日のOpenCupがなくなったらしい。これで2週空いたことになる。

朝方、さすがに何もやっていなくてまずい気持ちになったので、とりあえずPASTの残りの問題を解いた。MNO。

Mはなかなか苦行枠で、奇閉路があるなら頂点の値が1つ決まり、そうでないなら適当に定めてチェックすればよいと思っていたが、サンプルを試しているときに負の値が許されていないことに気づいた。幸い修正は容易で、二部グラフの場合のみ自由度があって色が同じ頂点すべてに同時に足してもう一方から引けるので、それで負の値を消そうとしてみればよい。実は「+ Graph」とほぼ同じ問題で、解説の方針も同じだったようだ。

atcoder.jp

Nは明らか。Oは、最初順列が与えられることに気づいていなかったのでしばらく迷走したが、なんとか解けた。ある部分木の値たちは、最終的に誰に負けることになるかが上から見ていくことで決定できるので、それとの大小関係だけ考えればよい。と思っていたら解説はもっと頭がよく、情報が矛盾しないならば勝敗が決まっている戦い以外はどちらが勝ったとしても対応する色の割り当てがただ一つ存在することから、その自由度を計算するだけで木dpっぽいことをせずに解いていた。

O問題をこの方針でコードゴルフして1時間半、さらにL問題のREの原因が添え字の和のオーバーフローであったことに気づき、それを直してさらに縮めるのにまた1時間半使った結果、午前9時になってしまった。明日は午後3時半から1on1で、まだ一切進捗を産んでいないどころか起きられるか怪しい時間になってしまった。急いで布団に入ったが、そこからうっかりハーメルンを1時間読んでしまい、午前10時就寝。

10/08(金)

午後2時半起床。シャワーを浴びたりしているうちに時間は過ぎ、結局ろくな進捗がないまま1on1に突入してしまった。

インターンはそういう契約なのだから、と励ましの言葉をいただいたが、この信用を失うのは怖い。自分ができないことをできると言うべきではないが、自分ができることをしないのはさらに良くない。とにかく今日は、ちょっとした勉強会として機械学習モデルの実装の説明をしていただいて、1時間弱で終了。

10/07(木)の朝方に投稿した短編小説は、一応pixiv小説の執筆応援プロジェクト・テーマ「夜」への応募作品として書いたものであった。昨日数回セルフRTした甲斐あってかPV数がかなり伸びており、確認すると「注目の応募作品」のところに自分の小説が載っていた。これはかなり嬉しいが、ツイッターのFF数と競プロ界隈の内輪ノリを頼みに無理やりPV数を伸ばした印象があって微妙な申し訳なさも感じる。そんな中、競プロ界隈と全くかかわりのなさそうな見ず知らずの人が、どういった経緯でか僕の小説を読んでくれて、面白かったとリプライしてくださったのが一抹の救いになっている。つまり、確実に僕の小説を評価してくださったということがわかるのだ。

1on1が終わってからすぐ大学に向かう。今日はおよそ20か月ぶりに対面でサークル活動が行われるようだ。ちょっと遅刻してしまったが、バチャをやっている静かな中にシュッと入って座り、自分もコーディング。今日のバチャはAOJ-ICPCから星の多い問題を選んだということで、実はほとんど解いたことがあったのでそれを再現するだけになってしまった。最後に初見の問題に挑もうとしたところで時間切れ。

AOJ-ICPCの500点に「薔薇園の魔女」という問題があって、初めて読んでから長い間解けていなかったのだが、今日のバチャで出てしまった。僕は不可能枠だと思っていたので見た瞬間飛ばしたが、1人時間内に解いたサークルメンバーがいて度肝を抜かれた。解法を聞いて感服し、帰ってから通しておいた。細かな実装テクとして、イベントソートして値を管理しつつ最大値を取るものは、値を減らす操作を増やす操作の前に並べると、ソートした後愚直に1つずつ処理していってよい。

AIZU ONLINE JUDGE: Code Review

これで500点の残りは「Spherical Mirrors」と「凸多角形柱工業都市」。両方幾何で逃亡の構え。

午後8時から三連続でコンテストに参加した。まず第一弾としてSRM815。18位で2540→2536(-4)。厳しい。

https://community.topcoder.com/stat?c=round_overview&er=5&rd=18891

EasyはbitDPやるだけ。制約が50×220で攻めてるな?と感じたが、冷静になれば余裕で間に合うことがわかる。Medは親の顔より見たグリッドを鏡写しに並べていく問題。丁寧丁寧丁寧に実装していたらルームの黄色が何人も僕より先に通していて涙が止まらなかった。Hardはよくわからない。大きい値から適当に貪欲みたいなことを考えていたが、どうにも正当性が信じられない。M^N\le 10^{18}以下という制約を各Nに対して考えてみたが、うまく分けてもどうしようもなさそう。最後に、適当に値の範囲を絞って全探索してみたが、N=7M=372のケースでTLEしてそのままコンテスト終了。

チャレンジフェーズ前は30位台で、部屋の提出もあんまり落とされなかったので絶望していたが、システスが終わってみるとバカスカ落ちていて18位になった。特に、Medを僕より速く解いた黄色が何人も落ちていて、ひどい話だが安心してしまった。別に僕がチンタラやっていたわけじゃなかったのだ。ただレートは下がってしまった。

次にyukicoder 317。全完。

yukicoder contest 317 - yukicoder

Aはよい。Bはdcで殴ってしまった。Cは全探索だが、0個の品物を選んでしまい1WA。Dは左右からdpしてマージ。Eは男女それぞれ誰まで見たかを持つdpで、遷移で頓珍漢なことをしており1WA。Fはそれぞれのバス停にいる確率の遷移行列を累乗するが、このとき1単位時間先の確率も持っておく必要がある。Gはセグ木。HはFでバス停3つを区別していたのを、バス停1とそれ以外の2つに分けて行列累乗し、1台だけ見たときバス停1以外にバスがいる確率を求めてM乗し、1から引けばよい。

Hはかなり面白く感じられた。ただ問題文が正確でない・(一般的な書き方をしていないため)読みにくい、という理由でコンテストに対してはネガティブな印象を抱いた。CとEが特別にひどく、TLではDの良い部分列の定義も不必要であると槍玉に挙がっていた。コンテスト後にいくらか改定されたようだが、この日記を書いている時点でやはりまだ読みにくく感じられる。こういうものはテスターが排除するべきではなかったのか。特にE問題は、問題文を忠実に解釈すると絶対に以下のツイート(Cと書いたがEである)の質問文のような解釈になるはずである、が、修正を執拗に迫るほどの熱意もないので、愚痴るだけ愚痴って放置。

さらにCF #747 div.2。途中寝てしまったが何とか全完。

Dashboard - Codeforces Round #747 (Div. 2) - Codeforces

Aはギャグ。Bはkを2進数展開してn進数として解釈する。Cは2回あれば全部の要素を操作できるので、1回以下でできるかを全探索。Dは各人に対応して真偽の頂点を作り、辺を張る。このグラフの作り方は実質2-SATだが、辺の特徴から真の人数、あるいは偽の人数を最大化できるということで、このことは直接グラフを作りに行ったほうがわかりやすい。E1は根が6通り、あとは上から見ていくとき一度分かれるとその後は独立だから、各頂点で4通りの自由度がある。指数を10^9+6で割った余りを計算したが、別にその必要もなかったようだ。

E2は面倒。自由度が4とならないような頂点たちは、すでに色が決まった頂点とその祖先たちだけで、高々O(nk)頂点しかない。これらについては各色の通り数を直接計算することにして、残った頂点の個数を数えて最後に4の肩に乗せて掛け合わせる。Fは問題文がちょっと難読気味だが、n項で総和sの数列であって、どの連続部分列の和もkとならないものが存在するかを答える問題。累積和を考えると、0\dots sから0sを含めてn+1個選び、どの2つの差もkにならなければよい。何個選べるかを考える。端から貪欲に詰めていけば、周期2kで埋まっていき、最後に余った個数とkのうち少ない方だけ使える。s=kの場合必ずYESになるが、これも処理できていると勝手に思っており、しかし全然そんなことはなく1WA。

問題が解けたので目が冴え、コンテスト後はしばらく日記を書いていた。朝方切り上げ、布団に入ってハーメルンを読んだ。1作読了。「東方古神録」。主人公のチート具合が好みで、結構面白かった。キャラも過剰に変な感じはしなくて、受け入れやすい。

東方古神録 - ハーメルン

午前9時就寝。

10/09(土)

午後8時起床。今日は夕方からCFで4hコンがあり、ちょっと興味を持っていたが、実際その時間に目覚ましで起きてみるとあまりの眠さに衝撃を受けた。耐えられず二度寝し、この時間になった。急いで食事してABC222。

Exawizards Programming Contest 2021(AtCoder Beginner Contest 222) - AtCoder

Aはどう書いていいか悩み、AWKprintfを使った。Bは適当にRaku。ここからはC++を使った。Cはなかなか実装が重めで大変だった。Dは自明。Eは辺ごとに通る回数をカウントすると、うまく±をつけて目的の値を作る問題になって、制約をよく読むと絶対値が105で抑えられるので、dp。Fはオイラーツアーして遅延セグメント木を作り、辺を行き来するたびに区間更新でその辺の重みを足したり引いたりした。Gは式を整理すると、あるmに対して10^i\bmod{m}が1になる最小の正整数iを求める問題になって、ちょっとだけ位数のことを考えたが、合成数modのBSGSを持っていることを思い出してそれを使った。最初答えが全部0になってキレそうになったが、確かに100が1であることに気づき、耐えた。答え0を検出しないようにライブラリを適当に書き換え、祈るように投げるとAC。

Hは、まずメモ化再帰で正しい値が出ることを確かめ、ループで直接求めるコードまで書いた。これは畳み込みっぽかったので、オンラインFFTをやれば解けるんじゃないか!?と思ってこの後ずっと実装していたが、結局合わせることはできなかった。そもそもオンラインFFTはlog 2つだから、107の制約では通らないか。

H以外の解説を読む。Fは木をちょっと拡張すれば直径の両端のどちらかが必ず答えになるらしく、なるほどなあという気持ちになった。G問題で使った合成数modのBSGSだが、今回のケースでは底とmodが互いに素でない場合必ず解なしになるので、最初少し探索してgcdを処理する部分が必要ないらしく、面白い。またオイラーのφ関数の約数を全探索する方法も紹介されており、こちらのほうが素直だったなと反省。

今日の昼頃にPixivランキング事務局からメッセージが来ていて、水曜日に投稿した短編小説が小説ジャンルのオリジナルウィークリーランキング83位に入ったことを知った。嬉しい……!小説を投稿した時のツイートのインプレッションは21000ちょっとだが、そこからリンクを踏んだ人は400人にも満たないようで、PV数のもう半分弱はどこから来たのかがよくわからないが、もしかしたらランキング経由で来た人がいるかもしれないと思うとワクワクする。

コードゴルフ。A問題はVimが最短になっていた。10000を足してから左端の1文字を削っている。そういえば、dcで出力の基数に10000を設定すると、10000進数のつもりなのか4桁で表示してくれたような……?と思って提出したものの、0は常に0とのみ表示されるらしくWA。Bはdcの22B解がほとんど自明で、僕はコンテスト終了直前までH問題をやっていて提出が22時40分過ぎになったのだが、22時38分の提出があって非常に悔しい気持ちになった。そのほかもコンテスト終了時点では何一つ最短を取れていなかった。このような状況はかなり久しぶりではないだろうか。衰えを感じる。

悔しいので、とりあえずC問題をRubyで、D問題をOctaveで縮めておいた。そうしているうちに午前2時になったので、FHC R3に出た。

Facebook Hacker Cup - 2021 - Round 3

ABD1の43ptで82位。R2を59位で通過したとき、Tシャツにバッジが付くのがR3の上位200人であることを知って残念に思っていたが、結局R3でもそれなりに良い成績を残せた。

ABcCを通して59位。R3進出、Tシャツ獲得に加え、上位200人なのでTシャツが何か特別仕様になるはずR3の上位200人に対する褒章らしい。ぬか喜び……。

週記(2021/09/20-2021/09/26) - kotatsugameの日記

Aは、更新をそれぞれ区間と見てマージしていけばよい。setで区間を管理するいつものやつだが、区間の端がどうなったら区間をマージできるのかを間違えたり、区間の左にあるものとマージし損ねたりして、サンプルを合わせるのにはそれなりに手間取った。Bは3列しかないため、行って戻って行って……のようにジグザグに動くことがない。考えるべきは、2点の間の移動方法と、2点からそれぞれ端のほうに行ってUターンしてくる場合のコスト。レベルで降順ソートするのは当然として、前者はセグメント木に3x3の距離行列を乗せればよい。後者は、Uターンする地点は近ければ近いほうがよく、これはsetで取得。さらにその間が通行できるかにはこれまたセグメント木が使える。安全性をとって定数倍悪めの解法を書いたら実行に結構時間がかかり、ちょっとヒヤヒヤした。

D1も値で降順ソートしてUF。以前に使ったロボットが同じ連結成分に存在するなら、それを流用できる。D2、D3については、UFのマージ過程を木にして、これの頂点とある点の間のパスに対していろいろ弄ることができればよさそう。HLDでできると思って、beetさんのライブラリを窃盗して1時間半格闘していたが、結局サンプルも合わなかった。

またABC222のコードゴルフに戻る。EはちょっとRubyで書いてみたら当然のようにTLEしたので、C++で清書した感じにしてお茶を濁した。FはRubyで、結構な時間を使って頑張った。

午前7時半くらいに布団に入り、ハーメルンを読む。2作ほど読了。

東方古神録~幻想幼女~ - ハーメルン

「東方古神録~幻想幼女~」。昨日読んでいた「東方古神録」の続編で、エタっている。

はりまり - ハーメルン

「はりまり」。霧雨魔理沙ホグワーツに入学する話。非常に面白かった。東方Projectにおける魔法とハリポタにおける魔法の違いの考察も興味深いが、何より魔理沙のキャラと立ち位置が好みだった。しかしこちらもエタっていて悲しい。

「はりまり」を読み終わったのが午前10時半。そこから午後1時半のHTTFまで3時間しかないが、ひと眠りしようと思って一度はスマホを手放した。しかし微妙に目がさえて眠れないこと、日曜日はHTTF以外に特に予定がないことなどを鑑みて、このままずっと起きていることにした。というわけでさらにハーメルンを漁って2作ほど手を出したが、片方は文章の拙さを我慢して読むほどでもないなと思ってしまい、もう片方は知らない作品の二次創作だったために、どちらも少し読んで投げ出した。

昼過ぎだったため、少し日記を書いて時間を潰し、午後1時半からHTTF。

デジタルの日特別イベント「HACK TO THE FUTURE for Youth+」 - AtCoder

途中までは非常に調子が良かったが、最後の1時間は全然スコアを伸ばせず、結局6位まで落ちてしまった。

A問題はビジュアライザをポチポチして1265823。このスコアはずっと更新されず、もしや理論値引き当てたか!?と思ってわくわくしていたが、openのほうで終了30分くらい前にもっと良い解が提出されていた。1x1ブロックはなるべく使わないようにしていたのだが、ビジュアライザを見た感じ思ったより使われていた。

B問題とC問題は全く同一のコード。まず、置いて印をより多く覆えるようなものを、タイブレークは盤面の中心にあるものを優先的に取るようにして貪欲に置いて行った。この段階では連結性を特に考えていない。次に、1x1ブロックを置いて全体を連結にする。2つの連結成分からそれぞれの代表点を全探索して連結成分同士の距離を出すのを全ペア行い、最も距離が近かった2つを実際に繋ぐ、ということを繰り返す。最後に、1x1ブロックに被さるように別のブロックを置いて、必要なコストが下げられる場合は置き換える、という操作を繰り返す。以上の3ステップであった。Bが1500000弱、Cが1890000ちょっとだった。

ここからさらに、1x1ブロックでつなげる際に縦と横のどちらを先に動かすかを両方試して少しスコアが上がり、以上のステップ全体を座標を調べる順番にある程度のランダム性を持たせたうえで時間の許す限り繰り返すことでBは1560000弱、Cは1900000弱になった。コンテストとしては、入賞を逃したし、抽選のアマゾンギフト券も外れてしまって残念。

昨日のABC222-Cが縮んでいた。配列の値をmapで加工してpで出力するとき、mapの中で出力するとsplat演算子が必要ない、というのは何度も何度も何度も何度も何度も何度も何度も見たのにいまだに忘れてしまう。絶望。

午後6時から少し遅刻してECR115に出た。コンテスト終了直前にGが通ったがその後Hackされ、現在6完。

Dashboard - Educational Codeforces Round 115 (Rated for Div. 2) - Codeforces

Aはよい。Bは選ぶ曜日を全探索して、2日とも行ける人と片方しか行けない人を数える。Cは数列の要素から平均を引くと、足して0になるようなペアを抜き去るしかないので、ちょうど平均と一致する要素だけ特別扱いして頑張る。わざわざ尺取りで数えたが、logをつけても変わらなかったかもしれない。Dは補集合を数える。片方が3つとも同じ場合はもう片方が必ず3つ互いに異なるので、両方2つずつ同じ値であるような3つ組を数えて引けばよいようだ。これは、(A,B),(A,\ast),(\ast,B)のような組だとわかるので、(A,B)を全探索すれば簡単に求まる。

Eは英語が読めなくて苦労したが、「右下右下……」と「下右下右……」のことを言っているようだ。数え上げは非常に面倒な気分になったが、差分更新にO(N+M)かけてよいことに気づき、愚直にどこまで伸ばせるかを求めて足したり引いたりしたら通った。FはbitDP。かっこ列典型の累積和を考えると、確かに使う文字列集合を決めれば末尾における累積和の値も決定し、それ以外の情報は必要ではない。ある文字列を足したとき、先頭からの累積minと現在の累積和が一致しているような場所の数がdpの値に足される。これは前計算で求められる。注意点として、ただ累積和の出現回数をカウントすると、'('で(累積和が増えて)終了するようなかっこ列をカウントしてしまう。文字列を足して先につなげる場合は、累積minが非負でなければならないので、そのチェックもする。

Gは落ちてしまった。まずn=|X|と置くと、片方がn桁の場合はもう片方は自由、そうでない場合は両方n-1桁にならなければいけない。片方がn桁の場合はそれほど一致しまくるケースが作れないだろうと思って愚直で書いた(ここを突かれて落とされたし、冷静になってみればそういうケースはめちゃくちゃある)。両方n-1桁の場合は面白かった。繰り上がりありでn-1桁ごとに和を取った文字列を用意して、Xの先頭1文字(これは'1'でなければならない)を取り除いた文字列を先頭にくっつけてZ-Algorithmすれば、もし求める位置があるならば2桁目からn-1桁目までは必ず一致する。1桁目は自分で削除したので、最後に文字列末尾の繰り上がり処理をキャンセルして一致を確かめればよい。

しばらくコードゴルフをしていたが、さすがに眠くなってきた。先に日記を書き上げて投稿する。予定通り日曜日は消えた。

10/10(日)

消えた。

週記(2021/09/27-2021/10/03)

09/27(月)

先週は週記を書いてからすぐ布団に入ったが、そのあとPixiv小説をちょっと漁ってしまい、結局寝たのが午前8時半だった。

午後1時半起床。しばらく布団でウダウダした後、大学生協に行って注文していた本を受け取ってきた。

午後3時からインターンの業務を進める。先週したことをまとめて、直後に迫った定例会で報告するための資料を作っていた。載せるデータを吟味していたら思ったより時間がかかり、ギリギリになって完成。発表自体は特に問題なく済んだが、そもそもデータが足りていないのでは?という話になって、アクセス権限が足りていない可能性があることが分かった。これは困った。とりあえず明日の1on1で話し合ってどうにかする予定だが、それまではすることがない。まあ今日は週末の疲れが残っているので、することがないならないで今のうちに体を休めておく。

Kaggleの新しいコンペが始まって、これはチーム制限が5人なので、ちょうどインターン先の興味があるメンバー全員が1チームにまとまることができる。早速チームを組むことになった。以前の週記で言及したかもしれないが、一応今Optiver云々というコンペに個人で参加してはいるものの、興味が離れて最近は手付かずだった。出だしで躓いていては世話がないので、何とかこの新しいコンペで自分なりのKaggleへの取り組み方というものを見つけたい。しばらくはコンペの内容だったり公開カーネルを読んでいた。

余った時間で、Kaggleに興味がある面々が集まってチームを組もうという話になった。チームを組むということ自体に非常に興味があって、ぜひやってみたかったのだが、残念ながらコンペのチーム人数制限が3人だったので組めなかった。以前は5人だったらしい。

週記(2021/09/06-2021/09/12) - kotatsugameの日記

CodeChefの先週のコンテストまとめ記事がメールで送られてきた。div.3の優勝者の部分に自分の名前が載っていて気持ちいい。自己顕示欲が満たされていくのを感じる。

ラノベを1冊読んだ。「王様のプロポーズ」。「デート・ア・ライブ」の著者・橘公司さんとイラストレーター・つなこさんのコンビの新作で、あらすじもかなり面白そうだったので、楽しみにしていた。実際素晴らしく面白かった。まず設定が自分の最近の好みにピッタリ一致していた。「最強の能力者」も好みだし、「主人公が学園長」も好み。しかも「学園長がその学園に通う」という展開に至っては、好みに好みが掛け合わさって掛け値なく最強に見える。そういうストーリーがありなのか。まさにコペルニクス的転回と言って過言ではないだろう。

序盤はいろいろ後に続きそうな展開が盛りだくさんだったので、もう何巻か出ることを見越して、1巻は準備の巻かなと思いつつ読んでいたが、思いのほかラストで話がまとまってびっくりした。非常に満足したが、2巻以降への期待が薄れたわけではない。あとがきによれば続刊が出ることが確定しているわけではなさそうだったが、ランキングを見るに売れ行きは好調なので、きっと出てくれるだろう。

実はかなり眠くて、ラノベを読んでいる間ちょっと意識を飛ばしたりしていたが、ラストが良かったので目が覚めてきた。次に「デート・ア・ライブ マテリアル」2巻を手に取って読み始めた。著者とイラストレーターの対談を読みながらその巻を思い返して非常に感慨深くなっていた。12巻などは男主人公がピンの表紙イラストになっていて非常に好みだった。この巻が出た頃に既刊を一気に買ったことを覚えている。

そこそこで切り上げて、ABC220-Eのコードゴルフをした。この問題はPythonによるゴルフがしばらく行われていたようで、なかなか短い計算式が以下のように最短を保持していた。しばらく考えていたら自分でも再現できたので、安心。

atcoder.jp

基本的に解説と同じ方針、つまり2頂点のLCAを固定して数え上げている。LCAの深さが0\le i\lt Nであるとすると、まずi+D\lt Nであれば答えに2^D\times 2^iが足され、さらにD\gt 1であれば、0\lt k\lt Dかつi+k\lt Nかつi+D-k\lt Nなるkの個数に応じて2^{k-1}\times 2^{D-k-1}=2^{D-2}かける2^iが足される。最後に、以上で求まった組の左右を逆にしたものを考えて、答えを2倍すればよい。2倍するのも2のべき乗を求めているときに行うことにすれば、i+D\lt Nのとき2^{D+i+1}を、また上の範囲の幅に応じて2^{D+i-1}を掛ければよいことになる。D\gt 1という条件は、この式変形によって必要なくなる。2^{D-2}を計算しなくなるし、D=1のときはkが取りうる値の範囲が常に0に等しいからだ。

さて、kの範囲をより精密に考える。区間の右端としてN-iまたはDを、左端としてi+D-Nまたは0を考えるので、この2×2を計算してminを取ればよい。計算すると、区間の幅は\min(2(N-i)-D,N-i,D)-1になるようだ。k=N-iとおいて場合分けすると、k\gt Dのときは\min(2k-D,k,D)=Dであり、k\le Dのときは2k-Dとなる。ここで区間の幅は正になる必要があるため、2k-D\gt 0よりk\ge\left\lfloor\frac D 2\right\rfloor+1が必要となる。

i+D\lt Nという条件はD\lt N-i=kと書き直せるから、結局1\le k\le Nに対してk\gt Dならば2^{D+N-k+1}+2^{D+N-k-1}\times(D-1)k\le Dならば2^{D+N-k-1}\times(2k-D-1)を答えに足す、とまとめられる。前者を2^{D+N-k-1}でくくり、kの代わりにk-1を考えれば、先の提出の式が得られる。

試しにdcで計算してみたところTLEしなかったので、それで縮めることにした。毎回2のべき乗を計算するのはまずいが、kのループを降順に行うことで、ループごとに2倍するだけで計算できるようになる。掛け合わせる数の場合分けは単純なminというわけにはいかないが、何とかして、73Bの解ができた。制約にD\le 2N-2がなくてキレそう。

atcoder.jp

布団に入って少しだけハーメルンを読み、午前8時前就寝。

09/28(火)

昼前、腹を壊して目覚める。トイレに行った後またすぐ寝て、次に午後3時半に目覚ましで起きた。午後4時の1on1のためにかけていた目覚ましだったが、ギリギリに起きるのも怖いものだと分かった。

明後日木曜日のCHUNITHMのアプデ情報が来ていた。もう見るからにラスボスですごい。@anayama_daisuke というラスボスの曲ばかり作っている人のアカウントが昨日の夕方にそれっぽいツイートをしていたので来ること自体はわかっていたが、作曲者が5人もいるのにはびっくりした。「ep. Grandioso」というマップ名も特徴的。

今日の1on1は、昨日から特に進捗もなく、やっぱりデータ足りていないですねという話になって、権限付与が完了するまではインターンに関係ないことを済ませておくことになった。具体的には10月第一週の木曜日に迫った4年ゼミの発表準備である。

1on1が終わって、あまりに眠いので布団に戻った。しばらくスマホを弄っていたが、午後6時半くらいに本格的なお昼寝の体勢になり、そのまま日付が変わるまで寝ていた。ここで日記の日付も変えておくのがよいと考える。

09/29(水)

午前0時起床。僕が寝ている間に権限付与が完了していた。素早い対応に感謝。

@anayama_daisuke というアカウントから、ラスボス曲の譜面の一部が動画でツイートされた。数年前に混沌で初めて見たときはびっくりしたが、これも恒例行事。25秒の動画からいろいろ情報が得られる。まず譜面定数14.0以上が確定し、この時点でレート理論値が16.00を超えることが分かったらしい。一体何色の表示になるのだろうか。またノーツ数は4444で、これはつい最近出た「赤壁、大炎上!!」を抜いて最多ノーツ数である。タップスライド以外での16分割タップも当然のように配置されており、新時代という感じが強い。

CF #744 div.3が始まっていたので、1時間遅れで参加し、1時間弱で全完した。

Dashboard - Codeforces Round #744 (Div. 3) - Codeforces

Aはよい。Bは先頭から合わせる。Cは作れるチェックを全部作る。Dはよく難しい問題の部分問題として見る設定で、多いもの2つをどん欲に組にしていけばよい。特に証明したわけではないが……いいだろう。個数の最大値が小さければそれだけ自由度がある。E1は後ろから見て残りの最小の要素を先頭に、それ以外を末尾に入れる。E2も後ろから見ると、その要素が絡む転倒数が計算できるため、小さいほうに振り分ければ残りの列はそれだけで考えればよいことになって、貪欲。Fは操作でANDを取ることになる列たちに分解し、それぞれ全部0になるまでに必要な操作回数を計算する。Gはdpで、現在の終点からすでにカバーした範囲の左右までの距離で状態をまとめられる。これでも状態が3次元だが、bool値のdpになり、実際1つの次元の値は最小値さえ考えればよいことが示せるので、2次元のdpに落とせる。

ARC084-D「Small Multiple」が縮められていたので考えていたら、大幅に縮め返すことに成功した。

atcoder.jp

01BFSをするため、配列の先頭と末尾に挿入する必要があって、コード長的にも実行時間的にも重かった。これを、コスト0で遷移するループとコスト1で遷移するループをうまく分けることで解消でき、しかも短くなったというのが驚き。リストを用意して先頭から走査する。コスト0の遷移についてはリストの末尾に追記することで、同じループでそのまま走査していってくれる。コスト1の遷移は、今見ているリストを書き換えることで次回のループの時に走査してもらう。コスト自体は外側のループで管理しているため遷移の際に考える必要はなく、ゴールにたどり着いたと判定されたら外側のループを抜ければOK。

デート・ア・ライブ マテリアル」2巻を読んだ。設定の話とかは非常に興味深く読めたが、正直ゲーム特典SSなどはゲームオリジナルキャラをよく知らないため、微妙……。あとは作中時間も大幅に前後しているため、あまり出てこないキャラがいたりするが、短編集として出されているわけではないため我慢できる。ゲーム展開もしているなんてすごいことではないか。

インターンの業務に関連して、新しく使えるようになったデータを処理するコードをずっと回していたが、全然終了する気配がない。このあたりのコードの改修をデータが非常に少ない状態で行えたのは、むしろ僥倖だったのではないかという気持ちになってきた。

午前10時になったのを見て、学食に行くことを思い立つ。営業時間を確認すると午前8時から空いているようだったので勢い込んで行ってみると、午前11時半からの開店だった。実は僕が見ていた営業時間の表は、10月からのものだったのだ。仕方なく、購買で少し買い物をした後は前の広場で1時間くらいハーメルンを読んでいた。

食事して帰宅。ツイッターを見ていると、「ゴルゴ13」で知られるさいとう・たかを氏が亡くなったとのニュースが流れてきた。生前から漫画の分業体制を整えていたという話で、この先もその体制を維持してゴルゴ13の連載は続けられるらしい。

ラノベを読んでいたが、午後3時くらいに急激に眠くなり、布団に倒れこんだ。午後11時まで寝てしまった。とんでもない生活リズムになった。

起き抜けに確認したこととして、まずCF #744 div.3のHackフェーズが終了し、全完が確定していた。次に、寝落ちするときにも動かしていたスクリプトがエラー落ちしていた。実際はPythonスクリプトいくつかをシェルスクリプトでまとめていただけなので、それ以前のスクリプト(8時間かかっていた!)の出力は保存されているが、エラーの原因がスクリプト名指定ミスでげんなりしてしまった。

今日の初めのほうで縮めたARC084-Dがさらに縮んでいた。Vim部分の更新で、ある行の左と右にそれぞれコードを挿入したい場合、IAを使うとセミコロンが必要になるが、Ioだと改行がコードの区切りになってくれるという話らしい。同様の手法が適用できるコードがいくつかあったので、探して縮めていた。

atcoder.jp

ゲノコン2021のシステムテスト・表彰式が終了して提出がすべて公開されたので、AtCoderProblemsでクロールされるようにプルリクを出しておいた。ゲノコン2021のD問題は、適当な文字列を2回出力するTextと、入力の1行目を2回出力するsedコードを提出していた。Textについては空文字列を2回出力する2BでACできたが、sedはさらに短く、pのみのコード1BでACできた。どうやら、出力の先頭2行を読み込んだら残り何が出力されていてもどうでもいいらしい。

Add genocon2021 by kotatsugame · Pull Request #1066 · kenkoooo/AtCoderProblems · GitHub

起きて落ちていることを確認したスクリプトだが、改めて実行してしばらく放置していたところ、どこからかキィーみたいな音が断続的に発生するようになった。恐る恐る部屋を調べていると、パソコンから出ていることが分かった。HDDのシーク音だろうか。確かにファイル読み書きが多く発生するスクリプトなので、しばらくは我慢だろう。で、我慢していると実行が終了した。これまで扱ってきたファイルよりサイズが非常に大きいらしく、書いたコードが一部動かない。とりあえず、ファイルサイズをヒストグラムにして確認したいと思ったので、サイズをcsvファイルに出力するのはPythonで、ヒストグラムOctaveなんぞ起動してちょっと弄っていた。いい感じのグラフができて満足。

あとは、今まで長い時間をかけて作ったデータを機械学習のコードに流し込んで動かす。スクリプトを実行してみると、今度こそパソコンのファンの音がすごいことになったが、触ってみた感じ熱を持っているわけではないので、安心。ただデータが増えたのでかなり時間がかかりそう。寝ている間に終わるだろうか。

布団に移動して俺ガイルの新刊を読んでいた。途中、「知識の泉」と「混沌の欠片」という単語が出てきて、GOSICKのネタだと気づいた。あまりにも脈絡がなくてびっくり。そういう風に出てきたネタであって、気づかず通り過ぎたものがいくらでもあるんだろうなあと残念な気持ちになった。

午前5時半就寝。

09/30(木)

午前9時半起床。すでにチュウニズムのアップデートの情報がいろいろ流れてきていた。レート16.00を達成した人も現れた。レートの色は変わらないようだが、称号が虹色に光っている。非常にカッコいい。この「皇帝」という称号は、チュウニズムの現行バージョンでレート16.00を達成することが条件のようだ。わざわざ現行バージョンという制限を付けたということは、次回作からレートシステムに変更が!?……というようなことを考えていた。無論僕の実力的にはほとんど関係のない話であって、ただのランカー厨。

せっかく起きたので、SRM814に出た。全完4位、2443→2540(+97)。SRMで全完するのは初めてかもしれない探したら2年半前に全完していた。

https://community.topcoder.com/stat?c=round_overview&er=5&rd=18888

Easyは前にしか進まなくてよいことを確認してやるだけだが、制約が5\times 10^5なのでスライド最小値でlogを落としておいた。Mは素因数分解して各素数の指数を見る。素因数分解100\times\sqrt{10^{12}}で、毎回やって間に合うか不安だったので、素数を前計算しておくことにした。置き換える値はALCAでよく、LCAが一致しない場合は必ず1個置き換える必要があることに注意。Medを落とした人はこれを見落としていたらしい?

Hardは2べきで作ろうとしたが難しそう。適当に1直線にマスを置いてみたところ、トリボナッチ数列が現れることに気づいた。フィボナッチ数列を適当に組み合わせると任意の正整数が作れることは有名だが、ではトリボナッチ数列では?と思って探索してみると、制約の範囲内(109以下)ではちゃんと作れることが分かったので、この方針で実装。1直線のマスの適切な位置から分岐して、残りが1本道になるようにしたい。別に3本くらい1本道を用意しておいて、そこに合流させることにした。分岐が連続すると、その間で移動ができてしまうな……と思っていたが、逆に連続した分岐はそこで1本道にまとめてよいことに思い至り、あとは右下を手作業で構築して完成。

昼頃1on1をした。昨日パソコンをぶん回した結果を報告した。データに不要な箇所が大量にあるという指摘を受けて、それを単純に削除して様子を見て、また明日の1on1で報告することになった。業務ばっかりやっているようだが学業は大丈夫か、と心配していただいた。そのあと閉店前の学食に急いで駆け込み、食事。

帰宅してラノベを読んだ。「やはり俺の青春ラブコメはまちがっている。結」1巻。年末年始の話を、由比ヶ浜結衣に着目して描きなおした感じだろうか。正直この辺り、本編で描かれたのが昔過ぎてあまり覚えていないが、覚えていなくてもエモいものはエモい。

チュウニズム14新曲の譜面動画がYouTubeに投稿されていたので視聴していた。MASTERで16分割ノーツが多用されているのは当然として、赤譜面にも16分割があってびっくりした。動画のコメントを見た感じでは振り下ろしエアーも赤譜面初らしい。

明日から新学期なので、履修計画を立てようとしたが、春先にダウンロードした資料を夏休みの間に削除してしまったらしく、新たにダウンロードしてくる羽目になった。院試に合格したので大学院の講義を先行履修することができるらしく、どんな講義があるのか調べてみたところ、4年生向けの講義と全く同じでびっくりした。つまり、同じ講義でありながら4年生向けとして履修すると学部の単位になり、大学院生向けとして先行履修すると大学院の単位になるらしい。学部の単位はもう足りているので、先行履修できないか4年ゼミの教員に聞いてみたいと思う。

午後7時過ぎからCF #745 div.1。10分こどふぉった。4完15位で2952→2998(+46)。あと2……。

Dashboard - Codeforces Round #745 (Div. 1) - Codeforces

Aから難しい。単純に4乗したくなるが不可能で、2乗で幅を決めた後、累積minなど使って高さを決定することにした。累積minの計算にも、ある行の区間内の'1'の個数を定数時間で求める必要があったりと、非常に面倒だった。

Bは非常に難しい。挿入dpでもどのように挿入するかが問題。大きい要素からどこに配置するかを決定するのが正解。今のところ最大値として何種類ありえるかをインデックスごとにカウントしておきたい。これまで配置した要素で数列はいくつかの区間に分割されるが、この区間内でカウントの値はすべて等しいから、区間の幅O(N)とカウントO(N)で状態をまとめることができる。それぞれ、区間内のgoodな要素の個数O(N)に対応して場合の数を持つ。遷移は、区間内のどの位置に要素を置くか、左右でgoodな要素がいくつあるか、でO(N^3)になる。O(N^5)で一度TLEを食らった。goodな要素はそれほど多くならないので、余計な個所を見ないようにすると通った。

Cはx_i+y_iの値が\sqrt nより大きいかどうかで処理を分ける。大きい場合はimosで愚直にカウント、以下の場合は\bmod{x_i+y_i}のテーブルを用意しておいて、そこを書き換える。imos法を使うことでlogがつかないようにした。おそらくそれを要求するためのTL 1secだろう。Dは、区間の最大値で分割して、マージに左右の列の長さの積だけかかるdpを書いたら爆速で通った。やっていることは、数列から作られるCartesian Tree上の2乗の木dpと同じらしく、このことから計算量解析ができるらしい。適当に投げてしまったが、面白い。

システスで上から4人ほど落ちて15位になり、LGMまであと2になってしまった。BとCで1ペナずつ吐いていて、どちらかがなければ14位だったのでLGMを達成していただろう。特にCのWAは、スコープ外の変数を書き換えるつもりで新しく変数を用意していたという理由だったので、非常に悔しい。処理を変えるしきい値を小さくしてデバッグするのをすっかり忘れていた。

「株では勝てる俺も、カワイイ女子高生には勝てない。」2巻を読んだ。1巻の個人的な評価は低めだったが、2巻は思いのほか面白く読めた。主人公に人間性がない描写は控えめになっていて、多少受け入れやすかった。ヒロインがディープラーニングで株価変動を予測しようとして、案の定莫大な損失を抱えてしまうという展開は、導入部分から破滅が約束されていて目も当てられなかった。それでもラストはいい感じに落ち着いたかと思ったが、急に不穏な感じの描写が挟まって心臓が休まる暇がなかった。

動画を見たりしているうちに、うっかり椅子の上で意識を飛ばしてしまった。ふと目を覚ますと、昼の1on1が終わってからずっと動かしていたスクリプトが最後の最後に「強制終了」と出て落ちていた。そういうエラーメッセージが出るような落ち方とはいったい何だったのだろうか。必要なデータは適宜ファイルに書き出してあったので、とりあえずそれを処理するコードを動かして布団に移動し、改めて寝た。午後11時半だった。

10/01(金)

午前6時半くらいに目を覚ました。その時はいい感じに眠気が残っていて、またしばらく眠れるはずだったが、うっかりスマホを手に取ってしまい全てが崩壊した。

Twitterで何かのゲームと東方がコラボしたときの霊夢が流れてきた。なかなか可愛らしい。

布団から出て、今日の夜にCFで行われるICPC WF MirrorにICPCチームで出るため、人をinviteしたりレジったりしていた。Slackに投げるとすぐ反応があったから、実は見てくれているんだなあと感動。僕が引きこもっているだけで、誘えば普通にICPC練習を連打できるのかもしれない。もしくはたまたま僕から誘ったから無理して出てくれたのか。

数時間かけて日記を書いて、読書記録もつけて、9月分の集計をツイートした。今月は結構読んだし、あまり本を買わなかったので、久しぶりに積読の数が減ったらしい。焼け石に水な気もする。

そのあとは今学期の履修登録をしていた。昨日も言及したが、改めて大学院の科目で先行履修したいものを選び、4年ゼミの指導教員にメールを出す。すると一瞬で承認してもらえたので、そのメールを証拠として含めて、改めて大学の事務方にメールを送信した。また、通常の履修登録の画面を開いて、1講時ずつ履修可能な科目を確認していく。科目名で気になったものがあれば、シラバスで内容を確認してみる、という感じ。

意識が高すぎてさらに2科目履修登録してしまった。「Pythonによるデータ科学入門」と「計算物理学」。どちらもPythonでプログラミングをする何かである。前者は、最初数回以降は対面で講義を行うというようなことが書かれており、不穏。しかし学部生活最後であることだし、講義棟まで足を運ぶのも一興か(こんなこと言っていて、どうせその日になれば行かない確率が高いが)。プログラミング関係では、探せばR言語を学ぶ講義もあったのだが、グループを作って発表しあうというようなことが書かれていてスルー。他に「インターネットを誰が守るのか」とか「批判的思考と論理的文章」という講義にも興味を惹かれたが、冷静に自己診断すれば面倒さが勝ることに気づけた。

これで今学期は講義を3つとる予定だ。それらのクラスコードを探してClassroomに登録し、ちょっと中を覗いてみた。まだ初回授業前なので、特に見るべきものはなし。

富士見ファンタジア文庫が、自社ラノベのキャラを集めて作ったクロスオーバーRPG「ファンタジア・リビルド」がある。ラノベの帯によく広告が出ていたので認識はしていたが、残念ながら今年の12月、公開から1年でサービスを終了することになったらしい。シナリオ担当もキャラも、ラノベ読みからしたら超豪華な布陣だが、ゲーム業界は厳しいものだ(プレイしていないのにどの口が言うか)。

午後になってしまったので、学食が閉まる前に急いで大学生協に行く。行きは普通に雨が降っているなあという感じだったが、ちょっと昼食を食べているうちに土砂降りになって、靴の中を濡らして帰ってきた。濡れた靴を乾かすため、わざわざ実家から送ってもらった古新聞を詰めていたら、その新聞がコロナ禍前のものであることに気づいて、ちょっと感慨深くなった。

自分は出不精なものだから、コロナ禍でも比較的影響を受けなかった人なのかもしれないが、影響がゼロというわけでは決してない。外出時にマスクが手放せなくなったとかそれ以前に、人が密集している状態に違和感を覚えるようになってしまったのだ。これはTwitterでもたまに流れてきた話で、過去の写真や動画などを見ていても、密な状態を検出して勝手に嫌な気分になってしまう。我々の認識の根幹を揺さぶってくる、そういうウイルスだったのだ。

そのとき考えていたことを時系列で並べているだけなので、話は変わるが、「ら抜き言葉」について。可能の助動詞「れる・られる」の使い分けは、付く動詞が五段活用・サ行変格活用の場合前者、それ以外は後者である。このことは高校生のころよこに教えてもらったもので、それ以来この判別に従ってらを入れたり抜いたりしている。僕が文章を書くときは、その判別でちゃんと思考が一時停止するため、週記でもら抜き言葉が出現しないようになっているはず。

眠気が強くなってきたので、午後5時の1on1まで1時間ちょっと寝ることにした。布団に入って人の週記を読んでいたら思ったより時間が経ってしまい、90分周期の睡眠が難しい状態になったが、強気のお昼寝。ちゃんと1時間時点の目覚ましで目を覚まし、しばらく布団の上で唸っていたものの、無事身を起こすことに成功した。

実は昨日の夜CFに出つつパソコンをぶん回していたので、1on1で報告すべき進捗はちゃんと用意されていた。いよいよ機械学習が本格化しそう。毎日作業を進めるのではなく、いったん時間を取って使いそうなモデルについて学び、実際にデータに適用して理解を深めることになった。

午後7時半から午後9時までまたお昼寝。今度も起床に成功して、yukicoder 316に出た。1時間で3完して午後10時からCFに出た。

yukicoder contest 316 - yukicoder

Aはよい。Bはコインの枚数を決め打って必要な操作回数の最小を考える。必要な操作回数の最小がk回だとすると、左端からkマスにはコインが置いてある必要があって、それ以降は自由なので、組み合わせで計算できる。Cはちょっと手で試した感じ0110の交換だけ考えてもよさそうな気がしたので、1がどれだけ動いたかを持ってdpしたら通った。後から解説を読んで証明を確認。操作によって、文字列の先頭から各1までの距離の和が変化しないことを使って示せるらしい。

残りは難しそうだと思ったので放置してCFに専念していたのだが、思ったより解かれていて順位がひどいことになった。ともかく、CFのICPC WF Mirror。5時間のコンテストである。

Dashboard - ICPC WF Moscow Invitational Contest - Online Mirror (Unrated, ICPC Rules, Teams Preferred) - Codeforces

ひどい目にあった。序盤EとHが解かれていて、Eはすでにチームメイトが取り組んでいたのでHを読んだ。Hは構文解析やるだけで15分で通ったが、以降L問題にハマり続けて4時間45分椅子を温めた。コンテストが終わってTLに流れてきたツイートを読んでもピンと来ていない。

しばらく日記を書いてから、朝方、ふとあるGitHubリポジトリのcollaborator一覧を確認したくなった。普通にGUIから見れるものだと思っていたが、認証付きAPIを叩かなければいけないらしい。調べたQiita記事ではPostmanを使って、通常の認証としてユーザ名・パスワードを入力しつつ叩いていたが、僕が試した限りではブラウザのURL欄に直打ちするのと同じく認証が必要であるとの文章しか返ってこなかった。やはりOAuthを使わなければどうしようもなさそう。公式ドキュメントを確認したいが、かなり眠気があって英語を読むのが辛いな……と感じていたら、日本語のドキュメントを見つけた。これに従ってやってみると上手くいったものの、自分が管理しているリポジトリでないとcollaborator一覧が取得できないらしく、結局ダメだった。

REST APIを使ってみる - GitHub Docs

布団に入って少しラノベを読んだ後就寝。午前7時半だった。

10/02(土)

途中何度か意識を取り戻した記憶はあるが、そのたびにまたすぐ寝直せていた。結局午後8時起床。

寝ている間にチュウニズム14新曲のAJが陥落していた。初日AJが出なかったのはバンキシャ以来だということで話題になっていた。バンキシャが追加されたのは僕がチュウニズムを初めてからで、それほど昔とは思っていなかったが、調べてみるとほとんど4年前の楽曲らしかった。

atgolferにいくつか更新が流れてきており、それらを確認しているうちに午後9時になったのでABC221に出た。G以外の7完。

AtCoder Beginner Contest 221 - AtCoder

Aはdc。プルプルしながらタイプしていたらFA+1秒だった。Bから面倒だったのでC++。Cは分割パターンさえ全探索すれば、それぞれは降順ソートするのが最適。Dは何も考えずに座圧してimosしたが、普通にソートした後カウント変数を管理するだけでも良かった。Eは「取り出した列の第2項以降が初項以上である」という条件だと勘違いしてしまった。この勘違いはサンプル4でしか落ちないので、念のため確かめてギリギリセーフ。誤読を修正するのにもいくらか時間がかかった。気づいてしまえばあとはBITで管理するものを変えるだけなので、簡単。Fは、まず適当に直径パスを取ってくる。直径パスの中心がちょうど頂点なら、そこから出ている辺の先にある頂点(十分な距離があるものだけを考える)をそれぞれ選ぶか選ばないかという話になる。2つ以上選ぶ必要があるので、ちょっとしたdpを行った。中心が辺なら、辺の両端の先にある頂点をそれぞれ選ぶ必要がある。

Gはしばらく考えていてもよくわからなかったし、そうしているうちにHのsolvedが増えてきたので、Hに移った。商で分類することをずっと考えていたが、それはO(N^2\sqrt N)になっていかにもまずそう。残り30分くらいで大幅に方針を転換した。冷静になると、Mの制限を外した問題がそのまま写像12相に存在する。玉も箱も区別せず、各箱に玉を1個以上入れるので、分割数P(n-k,k)というやつだ(ただし、コンテスト中は新しく箱を増やすときに玉を1個入れた状態で追加していたので、遷移が微妙に異なる)。全体に玉を追加したタイミングで、その後連続して箱をM+1回増やした場合の遷移先から前もって値を引いておくと、そこまで遷移していったときにうまいことvalidな状態のみを残すことができる。このことは、斜めに累積和を取りつつimos法を行っているとも理解することができるが、斜めに累積和を取るとか考えると頭を壊しがちなので、むしろ意識しないほうがうまくいくはず。

午後10時半からCFで何かのミラーコンテストがあったので、昨日と同じくICPCチームで参加した。結果はADBJGLIKHをこの順で通して9完。

Dashboard - COMPFEST 13 - Finals Online Mirror (Unrated, ICPC Rules, Teams Preferred) - Codeforces

Aから読み始めたが、Aが最も簡単な問題で、本当にこれでよいのかと首を傾げながら出したらFAだった。入力が106文字とちょっと怖いところだけが不安要素か。当時は気づいていなかったが、入力文字列がすべて同じ長さであるところから偶数番目の文字だけ反転する解法の正当性が簡単にチェックできる。Dは頑張って探索する感じの問題に見えるが、制約がギャグなので全探索できる。Bはどう見ても二分探索してくださいという見た目をしていて、その方針で考えた。適当にrを決め打った時にある点を含むような円は、原点から中心までの角度がある区間の内部に収まるという条件で表せる。この区間は円の交点の計算を流用すると求まる。そもそもどうやっても内部に含められない点をケアし忘れていて2WA。Jはチームメイトが通した。

このあたりでしばらく時間が空いて、100分ほど格闘してGが通った。最初の方針が、\sum_{i,j}\sum_{k,l}\gcd(a_i,a_j)\gcd(k,l)を求めた後うまいこと引き算して(i,j)=(k,l)なる場合のみ残すという方法だったが、これは結局iを固定してj\lt lに対して和を求めるような形が出現し、gcdを分離することができなかった。方針を大きく切り替える。ある数列\{b_n\}が与えられたとき、数列の要素の約数をそれぞれカウントしておくことで、値xに対して\sum\gcd(b_n,x)を求めるのを包除原理を用いてO(d(x)^2)(ただしd(x)xの約数の個数)で行える。個数カウントではなくて適切な値を足しておけば、重み付きgcd和も求まるので、まず数列の添え字の各約数に対応させて値をvectorなどに溜め、vectorの各要素をxvectorそのものを\{b_n\}として上記の計算を実行し、得られたgcd和を重みとして再度添え字の方で重み付きgcd和を求めればよい。

これだと約数の個数の2乗が出てきて、105以下の最大の高度合成数が約数を130個近く持つため、TLEしてしまう。同じ値が出現する可能性のある場所はmapを使って結果を持っておいたり、そのmapを使っていた箇所を配列(と配列の値を書き換えたタイミングを記録する列)で置き換えたりしたが、まだ間に合わない。ここで、O(d(x)^2)の部分は、xの約数のペア(p,q)であってp\mid qなるものを考えていたので、そのペアを最初に列挙しておくことにしたら、2sec弱で通った。

しばらく時間が空いたので、順位表で人間向け問題が一目瞭然になっていた。まずLは、dp_iへの遷移元の条件がj\lt iかつa_j\lt a_iかつa_i-i\le a_j-jと書ける。ここでa_iがpairwise distinctだとすると、a_iの昇順にiを見ていけばa_i-i\le a_j-jからi-j\ge a_i-a_j\gt 0が導けるため、j\lt iという条件を考えなくてよくなる。このことはpairwise distinctでなくても(a_i,-i)の昇順にソートすることで同様のことが言えて、a_i-iをセグ木のインデックスにすれば実家dpができる。方針だけ示して、実装はチームメイトに投げた。

次にI。\max(|a_x+a_y|,|a_x-a_y|)という式を分解すると|a_x|+|a_y|になったので、ほとんどギャグみたいなもの。更新はオイラーツアーして部分木に対する区間加算で行える。更新後に重みの配列を更新しわすれて1WA。このあたりでKの考察が完了していたので、マスがぴったり重なるコーナーケースを指摘しつつ見守っていたら通った。Hも思ったより簡単で、部分文字列bを受理するオートマトン上でdpするいつものやつ。Aho-Corasickのfailure関数みたいなものを計算する必要があったが、制約が小さいので愚直にやっても間に合う。

そのあとはE問題を考えていたが、パスのコストを単純に辺の本数で定めた場合の問題すら解けず厳しい。終了間際にC問題の解法っぽいものがチームメイトから出てきたが、実装する時間がないなあとなって終わってしまった。E問題は重心分解らしい。さすがにこの段階で未履修なのはまずいか。

ABCに戻ってコードゴルフをする。A問題はコンテスト中のdcコードでよい。B問題はPerlで文字列のxorを取る解を提出していたのだが、print関数ではなくprintf関数を使っており、そこで1B短縮されていた。さすがに呆れかえった。Cは文字ごとに分解して降順ソートし、2数の小さいほうの末尾に貪欲にくっつけるとよいらしい。Vimの48B解がすでに存在しており、Perlで同じく48Bに至ったがそこからは縮まない。Vimのほうで考えて、文字ごとに分解した後各行の末尾に文字列を挿入している部分を置換コマンドで一気に行ってみたところ縮んだ。DはPerl解をちょっと縮めたところすぐ取り返された。区間の始点と終点を区別する必要があって、Perlでは文字列に空白や改行が含まれているかどうかをチェックしているが、ほかの言語で実装しようとすると新たに別のデータを持つ必要があって難しそう。

このあたりでABC-Gを通した。kyopro-friendsさんのツイートを参考にして解いていたが、全然TLEが取れない。仕方なく公式解説を見たら、bitset<3600001>を2001本持ちますと書いてあってひっくり返った。僕の実装でも、縦と横を同時に復元するようにしたら通った。定数倍2分の1が効きすぎている。その後bitsetを大量に持つ解法でも通しておいた。

コードゴルフを続ける。EFは飛ばして、Gを縮めた。Ruby多倍長整数をbitsetのように扱うと、必要なだけのメモリしか確保されないので軽め。C++で書くより速くてびっくりした。しばらくチマチマ縮めて167B。文字列"Yes"と復元した解を出力するのに、sumメソッドの引数に"Yes\n"を指定すると縮んだのが面白かった。Hは当時の最短を単純にCrystalで書き直しただけ。熨斗袋さんのユーザ解説と同じ遷移で、実のところ僕のコンテスト中の解法とも、貰うdpと配るdpの違いだけでほぼ一緒のようだ。

さらにABC前にatgolferに流れてきていた更新もいくつか取り返した。Rubyである非負整数の変数iが0に等しいとき0、そうでないとき1を得るのは、これまで-2[i]を使っていたが、負号が付くことを許容すればi/~iでも計算できる。これでさらに2問ばかり縮めることができた。

そんなことをしているうちに昼前になってしまった。来週木曜日に迫った4年ゼミに向けて、しばらく前学期の最後のほうの発表を復習していた。正午を回ってから布団に入り、ラノベを1冊読了。

VTuberなんだが配信切り忘れたら伝説になってた」2巻。今巻は前にもまして例のアレのネタや下ネタ・コピペ・パロディが盛りだくさんで、ちょっと正気では読んでいられない。しかし作中世界にどっぷり浸かると面白く読めた。特にシリアスなシーンが多かったりするわけではなく、正直シリーズとしての内容はあまり覚えていないが、読後感がまったりしていて非常に良かった。後書きで、次巻にはweb版で屈指の人気を誇ったシーンが収録される、ということが書かれていた。気になる。今すぐweb版を読みに行きたいところだが、ぐっとこらえて3巻の発売を待ちたい。かなり売れているらしく、続刊することはほぼ確実らしい。

10/03(日)午後2時半就寝。

10/03(日)

午後6時起床。第8回PASTの過去問が公開されるかもと思って1時間おきに起床して確認していたのだが、その時にDMでSUSURUがゆゆうたとコラボしてやばいクレーマーのSUSURU TVを歌ったことを知り、飛び起きた。

ゆゆうたからツイートされたほうの曲(特にラストのフレーズ)、ほとんどSuper Driverに聞こえる……。勢いの良い曲調が共通しているが、それに加えてコード進行とやらも同じだったりするのだろうか。

しばらくコードゴルフをした後、昨日の続きで4年ゼミの発表の復習をしていたが、また途中で切り上げて午後11時半からCF #746 div.2に出た。

Dashboard - Codeforces Round #746 (Div. 2) - Codeforces

F1までの6完。Aは大きなほうから2つ取って交互に使うのが明らかに良い。Bは両端からそれぞれn-x要素を自由に並べ替えられるので、その範囲が数列全体を覆っていれば良いし、そうでなくても、実際にその部分だけでソートしたら全体が揃うような場合も良い。Cは、適当に分解した結果の連結成分3つを、全体のXORを変えずに纏めることができるので、分解するのは2つか3つであるとしても良い。2つの場合は簡単で、木全体のXORが0ならば(またその時に限り)適当に1頂点抜けば達成できる。そうでない場合は、分解した各連結成分のXORが定まるため、木全体から2つ抜けるかをチェック。切る辺2本の片方がもう片方の祖先になっている場合は注意が必要。ちょっとした木DPを行ったが、帰りがけ順に頂点を見てXORを計算しつつ切り離していくと処理がまとめられて簡単そう。

Dは、どこかの辺が答えになるとしてよい。辺全体を半分に分けていった。分けるときは、現在残っている辺からできるだけ連結になるように選び、選んだ辺たちに含まれる頂点を聞く。その中に答えと一致するものがあればよいし、なければ以降選ばなかった辺たちを聞くときに今聞いた辺の情報が邪魔になることがない。木の辺をdfs順に並べて二分探索という解法を見たが、結局それも今言った「できるだけ連結になるように選ぶ」を満たそうとしているという理解でよさそう。Eは、まず区間の長さが偶数でなければならないことがわかる。そのときANDで残るbitを決め打つと、それ以上のbitは全部XORで消える、つまり偶数個なければならない。これはZero-Sum Rangesの要領で累積XORを持っておけば求まる。ANDで残るbitも含めてキーにすれば、区間の長さが偶数であるという条件も同様に書けるため、楽。mapを書き換えるのは計算量が悪化してまずいので、配列とそれを書き換えたタイミングを持って頑張る。このテクは昨日のCF 5hでも使った。

F1は、左下と右上の操作は左上の操作2回で再現できるため考えなくてよい。右下の操作は高々1回しか行わないようなので、それを全探索して、残り左上の操作は貪欲に決めてよい。隣り合うマスが異なるかどうかを持っておくと、右下の操作では1列の高々O(n)箇所しか変更しないので、差分の計算もO(n)で行えて全体で3乗になる。実装を安全側に倒してそこそこ定数倍の大きなコードを書いたら1300msくらいで怖かったが、通った。F2も左上と右下の操作しか考えなくてよいことは同じだったが、右下の操作が何回も行われる可能性があって、それを最適に選べなくて解けなかった。僕は「隣り合うマスが異なるかどうか」を見ながら計算しようとしたのだが、それよりも「どこのマスを右下にして操作するか」を最初の状態で求めて、これを適切に右下の操作で置き換えることを考えるのがよかったらしい。この見方の元、二部グラフの最大マッチングに落ちるようだ。

水曜日にAtCoderProblemsに出した、ゲノコン2021をクロールするようにするプルリクがマージされたので、atgolferのほうも対応させておいた。

add genocon2021 by kotatsugame · Pull Request #21 · kmyk/atgolfer · GitHub

また4年ゼミの復習の続きをして、今度こそ最後の発表まで読み終わった。次回自分が発表する番なので、担当することになる箇所を読んで式変形を追っていたのだが、埋まらない行間を1か所見つけてしまった。教科書を見返しても、まだ証明されていない事実を使っているように見える。今読んでいる章では素数定理と同値な命題を大量に示したのだが、素数定理そのものはまだ全然示していないため、使って良い命題とそうでない命題を慎重に区別する必要があった。

考え込んでいるうちに椅子の上で意識を飛ばしてしまったらしい。ふと気づくと時間が1時間くらい飛んでおり、変な体勢だったので首が痛いし、寝ながら舌を噛んでいたらしくそこも痛い。満身創痍で布団に潜り込み、改めて就寝。午前4時半だった。

そういえば、第8回PASTの過去問は(この部分を書いている2021/10/04(月)午後3時時点で)まだ公開されていない。

週記(2021/09/20-2021/09/26)

09/20(月)

先週の週記を投稿してからの話。まずECR22の続き(EF)を解こうとした。F問題は諦めたが、E問題について。

Problem - E - Codeforces

全然解けない。しばらく唸って、このレベル帯の問題を取っておく必要性は薄いと考え、諦めて解説を読むことにした。ある要素を取る条件は、それと同じタイプの要素であってk個前にあるもののインデックスを見て、現在処理している区間より左側にあるかどうか、と言える。この言いかえをすると、求める要素の個数は「ある区間内のある値未満の要素の個数」とできて、ソートされた区間を持つセグメント木で数えられる。自分はrangefreqというライブラリにしていた。

次にECR23を埋めた。

Dashboard - Educational Codeforces Round 23 - Codeforces

Aはよい。Bは場合分け祭りかと思ったが、ちゃんと整理するとそうでもなかった。Cは難しかったが、問題タグに二分探索とあるのが見えて、その方向で考えてみると非自明に感じられる単調性が見つかった。興奮してコーディングしたらlong longのつもりでlongと書いてしまい、CFでlongは32bit整数なのでWA。昔一度やらかしてからは常に意識していたので、引っかかったのはかなり久しぶり。Dはmaxとminそれぞれの和が計算できて、答えがその差として表せる。EはBinaryTrieのverify用問題。Fは区間の端だけ取り出し、遅延セグメント木に0と1の個数を持ちたい。実際には個数を持つ必要はなく、0・1が存在するかしないかをboolで持つだけでよい。作用素が微妙に準同型になっていない(単位元で壊れている)気がするが、幅0の区間に作用させることは考えなくていいのか、通った。

布団に移動してハーメルンを少し読み、午前11時半に寝落ちした。

僕の主観において月曜日は消滅したが、実際はこの後日付が変わる前に一度起きている。その時のことは火曜日の欄に書いた。

09/21(火)

09/20(月)午後9時くらいに少し目を覚まし、ハーメルンを読み進め、1作読了。「無自覚な吸血鬼の王」。勘違い物を目指していたのだろうけど、よくわからないなあという感じ。主人公の能力・来歴はその多くが謎のままエタってしまっている。また主人公のキャラもあまりに悲観的に感じられて好みではなかった。

syosetu.org

また別のハーメルンを開いて少し読んだところで再度就寝。次に日付が変わって、09/21(火)午前2時くらいに目を覚ました。

さらにハーメルンを読み進め、午前4時くらいに1作読了。「東方神零録」。主人公のノリがキツいが、直球でハーレムを作っているのが目新しかった。東方は女性キャラが多く、二次創作でオリ主が複数のキャラから好意を寄せられているのはよく見るが、実際に(それも複数と)深い仲になる作品は限られている気がする。

syosetu.org

もう1作読み始め、適当に斜め読みして1時間ちょっとで読了。「東方創造伝」。何らかの評価を下せるほど話が進んでいない。

syosetu.org

東方オリ主古代スタートのほとんどは、最初にオリ主が古代都市の近くに降り立って八意永琳と出会う。それで、しばらく古代都市で生活するのが定番の流れなのだが、正直古代都市の描写にはほとんど興味がない。月に移住してからは竹取物語の時代まで出てこないし、出てきたとしてもキャラクターだけで、古代都市自体は完全に消滅して現代に続く文明には一切関わらないからだ。

午前6時くらいになって布団から脱出した。食事して午前7時からインターンの業務に手を付ける。以前書いたコードは途中でエラーを吐いていたが、その原因となった自分の勘違いを1on1で修正してもらっていたので、コードを書き直す。一度書き始めたらこっちのもので、パパっとやって3時間くらいで一通りの完成を見た。完成というのは、プログラムが最後まで動いているということ。これで今日の午後に予定されている1on1で報告する内容には困らないだろう。1on1駆動開発……。

書いたコードは現在GPUを使用して動いている。試しにCPUで動かしてみたところ、思っていたより何十倍も遅くてびっくりした。こんなに違いがあるのなら、それはインターン先もわざわざPCを送ってくれるというものだ。

ICPC国内予選の競技ルールが発表されていたことを知った。今年はチーム3人がそれぞれ個室から参加しなければならないらしく、びっくり。でもサークルとして参加場所を確保する必要がなくなるから、その点楽にはなるのかもしれない。まあもともとサークルとして参加場所を確保する必要はないのだが、個人的な思想として3人集まって出てほしいというものがあり、それをサークルメンバーに押し付けるならば、義務として参加場所は確保しておかなければならなかった。

2021 国内予選 特別競技ルール | ICPC 2021 Asia Yokohama Regional

ECR24を開いて少し解き進めた。とりあえずA-Dまでを埋めた。

Dashboard - Educational Codeforces Round 24 - Codeforces

Aは算数。Bはやるだけだが、うっかりミスで1WA。Cはsolvedが少ないのを見て身構えていたが、実装がややこしいだけでアルゴリズム的には普通の累積和。4方向それぞれ計算するときの和を累積させる向きとか、ドミノが横に置かれているか縦に置かれているかでコードを変えなければならないとか、面倒さはピカ一だったが、一発で通ってうれしい。

Dは一見してわからなかったが、出かけようとシャワーを浴びていたら思いついた。すべての色について調べても、計算量は全体の要素数で抑えられる。

先週金曜日の日記にも書いていたが、入学意思確認書の提出期限が明日に迫っている。今日提出しに行くことにした。

大学院に合格したはいいものの、入学意思確認書を提出できていない。今週はもう終わってしまった。期限は09/22(水)である。火曜日あたり徹夜して直接教務課に出しに行きたい。

週記(2021/09/13-2021/09/19) - kotatsugameの日記

原付に乗って山に登る。教務課にたどり着いたのが午後1時ちょっと前だったが、その時間帯はちょうどお昼休みだった。仕方がないので食堂で食事した後、ハーメルンを読んでしばらく時間を潰す。ベンチに座っていたら目の前に鳥のフンを落とされてびっくりした。危なかった。

問題なく提出完了。これで本当に大学院への進学が決定したと言える。山を下り、川内キャンパスの生協に行って先週水曜日に注文していたラノベを受け取り、散髪して家に帰った。散髪の間はほとんど意識を失っていたが、時たま頭を起こすよう促されたことを覚えている。

注文したのは6冊で、うち1冊は在庫がなく、取り寄せている最中らしい。それにしてもまだ入荷連絡の音沙汰がないとはびっくり。重版待ちだろうか。

ECR24の続きを解く。今回はEからGまでちゃんと通せた。

Dashboard - Educational Codeforces Round 24 - Codeforces

Eは素因数ごとに尺取り法をする。初期値を間違えていて1WA。Fは何を思ったか、「辺の半分以上が橋」を「頂点数の半分より多く橋が存在する」だと思っていてO(1)算数をしてしまい、1WA。すぐ二分探索に直して通したが、問題タグを見てしまったのが効いているかもしれない。

Gも問題タグを見たのが効いていて、フローを流した。これはECR22-Dの強化版。ECR22-Dはdpでも解けたが、問題タグにフローがあるのにびっくりしていたのを覚えている。今回の問題はフローでないと解けない。

Dは2つの部分列を作るのに、現在見ている要素が先頭になっていないほうの部分列の先頭を持っておくdp。問題タグにflowと書いてあってびっくりした。

週記(2021/09/13-2021/09/19) - kotatsugameの日記

ECR25のA-Dを通した。

Dashboard - Educational Codeforces Round 25 - Codeforces

Aからコーナーケースに引っかかってキレていた。与えられた文字列の末尾が0だと、さらに1桁0が送られていると見なさなければならなかった。Bは実装するだけだが、左下方向の斜めをすっかり忘れていて1WA。CDは貪欲。Eも適当に貪欲しようとしたが、2回ほど嘘解法を投げて、結局わかっていないまま放置している。

午後5時からインターンのメンターさんと1on1。今日の朝やったことを話して、この先数日やることを決めた。また働き方に関して、1on1がないとサボりがちになってしまうので、頻度を増やしたいということをお願いした。1on1が終わってから、微妙にやる気がある今コーディングするべきだと感じ、しばらくバリバリコーディングしていたら、次回までにやることとして設定したものが完成してしまったので、慌てて明日にも1on1をお願いした。

新サークル長から、コロナ禍前の活動がどのようなものだったかについて質問を受けた。確かに彼は今大学2年生で、入部時点で全ての活動がオンラインになっていたのだ。個人的には、僕がサークル長になってから対面で活動していた時期はずっともくもく会と称して本当に黙ってコーディングしていただけだったので、オンラインの活動に移行してからは内容も充実したし、教室の予約の手間もなくなって良かったなと考えていたのだが、それはそれとして対面で活動していた文化が今まさに喪われようとしていることに気づき、愕然とした。

しばらくパソコンの前に座っていたが、眠気がひどくて椅子の上で意識を飛ばしてしまったので、布団に移動して就寝。午後11時だった。

09/22(水)

午前4時くらいに一瞬起きたが、ちゃんとすぐに寝なおすことに成功した。次に、午前6時半くらいに目を覚ます。今度は二度寝できなかった。しばらくハーメルンを読んでいて、午前9時くらいに布団から出た。

ちょっとコードゴルフをした後、最短コードを収集するクローラーを久しぶりに動かすことにしたが、動かない。調べてみたところ、AtCoderProblemsのAPIが変わっていて、個人の提出を全件取得するAPIが無効になり、代わりにある時刻から500件分を取得するAPIが提供されるようになったらしい。

適当にコードを書き直す。提出を全件取得するのに、時刻0を指定して取得→取得できた最後の提出の1秒後からまた取得→……を繰り返すことにした。完全な同時刻に2つ提出があると壊れる可能性があるな、とは思っているが、必要なのはACしたことのある問題リストで、今のところは漏れなく検出できている。経過を出力してみると、どうやら僕の提出をすべて取得するためにはこのAPIを103回叩かなければならないようだ。スクリプトを起動するたびにそのようなことをしているとまずいから、ファイルに書き出しておくべきかもしれない。

昼前に家を出て、大学生協で買い物をし、ゲーセンに行った。今日は3時間くらいプレイした。なかなかいい成果が出た。

まず新しく解禁した曲について。12+、13、13+をそれぞれ1曲ずつ解禁し、12+と13ではAJを、13+ではSSSを出した。特に13+のSSSは(何度も譜面動画を見ていたということもあり)初プレイで達成できた。記憶にある限りでは、13+の初プレイでSSSというのは今日が初めてな気がする。これはAJも狙えるのではないかと思ってもう何回かプレイしたが、結局初プレイのスコアすら超えられなかったのは残念。初見プレイが微妙に上手いというのは音ゲーあるある。

また、HAELEQUINでSSSを出した。これで13+の未SSSは3譜面になった。先週水曜日の時点で敷地帯の運指さえ組めれば出ると言っていたが、実際そのようになった。肝心の運指は餡蜜で、SSSを出したプレイではそれ以前もめちゃくちゃ上手く行き、敷地帯直前で1-0、敷地帯抜けて3-0。今日は最後の変なリズムの交互が下手くそで、案の定1-1出してしまったが、それまでが望外に上手かったので耐えた。

今日プレイした感じでは、敷地帯の運指をちゃんと組むことがSSSを出すことの(必要かつ)十分な条件だろう。

週記(2021/09/13-2021/09/19) - kotatsugameの日記

他に、初音ミクの激唱でAJを出した。13+のAJは2譜面目だが、狙って出したという意味では初めての経験。かなり前に1-0を出してから、ほとんど噛み合い待ちの様相ではあったが、13+のAJに対する現実感がなく、今日まで本気で狙うプレイをしたことはなかった。3ヶ月くらい前に13+のAJがポロッと出たので、今日念入りにやってみることにした。

13+のほうもSSS出しておくか、と思って詰めていたら、なんと一気にAJが出てしまった。13+ではこれが初めてとなる。

週記(2021/06/14-2021/06/20) - kotatsugameの日記

実際、譜面の中で押せない部分はなく、安定しなかった鍵盤も入りの配置を覚えたらほぼほぼ通るようになった。今日詰めている間に一度99精度も出たのだが、AJ時のプレイでは安定を取って縦連を擦ってしまったこともあり、赤はそこそこ出ている。それでも堂々13+の最高スコアであった。

帰宅して急いでシャワーを浴び、午後4時から1on1。昨日コーディングした内容を報告し、微妙に出ていたエラーを解消してもらったり、その結果見つかったバグを直したりした後、さらにやることを決めた。午後5時からはミーティングで、今週も何事もなく終了。

大学生協で本を10冊注文した。新刊のチェック漏れがあって、2回に分けて注文してしまったが、支払いなどは結局のところ大学生協の店舗で行うので、特に損しているわけではない。しかしなぜチェック漏れが発生したのかが謎。漏れた新刊も発売されることは認識していたので、どこかでもう買ってしまったのではないかと購入記録を確認したりしていた。

溜めていた日記を書いた。火曜日の欄にICPC国内予選の競技ルールの話を書いたが、チーム3人がそれぞれ個室から参加しなければならないという文面が消えており、前年と同じく集まっても集まらなくてもよいとされていてびっくりした。

2021 国内予選 特別競技ルール | ICPC 2021 Asia Yokohama Regional

日記を書き終えてからパソコンを弄っていたら、椅子の上で意識を飛ばしてしまった。急いで布団に移動し、就寝のツイートをする。しかし微妙に目が冴えて眠れない。スマホを触って、Twitterで流れてきた「Vtuberの姉はオンラインで生きている」というnote記事を読みふけってしまった。

Vtuberの姉はオンラインで生きている|しじみ|note

ところどころにドキッとする言及がある。家にお金を入れないとか、母の日にプレゼントを用意しないとか。特に、僕が親にプレゼントを贈ったことがないことを思い出し、いたたまれない気持ちになった。せっかくインターンを始めたのだし、9月の給料が入ったら何かすることを考えたい。親に諮ってみよう。

日付が変わったあたりになって、決心してスマホを手放し、積極的な睡眠を試みたところ、意識を落とすことに成功した。

09/23(木)

午前5時すぎくらいに目を覚ます。TLにPixiv小説が流れてきて、それを少し見た後勢いに任せてほかのものを色々読み漁っているうちに、眠気がすっかり消えてしまった。ちなみに、主に「転生したらスライムだった件」のリムル愛されSSを読んでいた。

通知が行かない引用ツイートについて。以前まで、ツイートのリンクをコピーした後、URLのユーザーIDの部分を別の文字列に変えてツイートの文面に含めることで、本人に通知が飛ばないまま引用ツイートができるという仕様だったが、いつの間にか使えなくなっていた。そのあとどこかで、ユーザーIDの先頭に@をつけるといいらしいと聞いたので、試していた。kotatsugame_tのアカウントからatgolferのツイートをそのように引用して、atgolferから確認すると、確かに通知は来ていないようだ。しかしツイートのプレビューも表示されないため、引用ツイートとしては片手落ち。

atgolferに久々にログインしたので、ちょっとbotの運用について考えた。具体的には、botからフォローを飛ばすべきか否か。僕はkotatsugame_tのフォロー方針、つまりフォロバ100%を第一義としているので、フォローを返さないのは何となくむず痒い気持ちになるが、一方atgolferを作ったkimiyukiさんにはその方向のこだわりはなさそう。しかし以前から5フォローだけしてあったのがどうにも中途半端に思えて気になっていたので、少しだけ増やすことにした。フォロワー欄を見て、僕がatgolferで名前を見かけた覚えのある人をフォロバした。僕としてはこれで運用方針の統一性があると思えてスッキリ。

今日は午後1時からACPC2021 day1があるが、それまでしばらく時間が空いた。微妙に眠気が出てきたので、眠らないようにラノベを1冊読んだ。「お見合いしたくなかったので、無理難題な条件をつけたら同級生が来た件について」2巻。1巻から少し時間が空いたので話の内容を一切覚えておらず、当時の日記から復元しようと思ったが、設定に関する違和感しか書かれておらずちょっと困った。思えば、日記に本の感想をある程度細かく書くようになったのはそこそこ最近だったかもしれない。

登場人物が軒並み名家の御曹司・令嬢だった

週記(2020/11/30-2020/12/06) - kotatsugameの日記

ただ、1巻の内容をあまり覚えていなくても面白かった。特に、上で引用したように1巻の感想で触れていた設定に関する違和感が解消された。どうやら身分差のある恋を描いているらしい。そういうテーマは童話などではよく聞くが、現代社会を舞台にしたラノベで取り扱おうとすると、登場人物が軒並み上流階級の人間になってしまうのだろう。目新しくて面白い。また合間合間に挟まるやけに不穏な別視点の文章も楽しめたが、受け取り方は読むときの精神状態によりそう。2巻では主人公とヒロインがかなり近づき、いわゆる両片思いになっていると考えられる。その状態は健康にいいが、ここで身分差が火を吹くらしい。3巻が怖いが、楽しみでもある。

↓このツイートは2巻の文章の一部について。

午後1時になって、ACPC2021 day1にソロで参加した。結果は8完4位、個人勢としては2位のはず。説いた順番はABDFGHECなので、その順に感想を書く。

https://onlinejudge.u-aizu.ac.jp/services/room.html#ACPC2021Day1

Aは、Tの分割方法を全探索して、各行で揃った部分を持つbitDPをした。解説の方法がシンプルでびっくりした。Bは319を気合で通す。部分集合を全部舐めるときに、最上位bitだけ取り除いておくとループ回数が半分になることを利用した。ループが足りず1WAしたが、FAだった。OR畳み込みを条件を満たすまで繰り返すのが想定解らしい。Dは、部分集合の全域木の個数をそれぞれ行列木定理で求めておいて(bitDPでなんとかできるかと思ったが、できなかった)、あとは3つの市に分けるのをまた3^Nで行う。市をまたぐ道路をカウントするのにNかけるとまずいと思ったので、頑張ってO(1)で引けるようにした。1つの市を取り出すのは2^Nでできて、そのループ内で別に部分集合を渡るループを回し、部分集合からさらに1要素を抜いた時の値を用いて現在の部分集合の値を計算する。実際にはNかけてもよかったらしい。

Fはパッと見難しい。前から貪欲かな~など思ったりしたが、よくわからない。しかしこの時点で一番solvedが多いということで、ボンヤリとあれこれ考えていたら、ふと操作2が可逆であることに気づいた。なので、最初に操作2を行えるだけしてよくて、得られた文字列の部分列としてTが含まれるかを見ればよい。含まれる場合は当然一致させられて、含まれない場合は、もうこれ以上文字を増やすことができないため不可能。Gは2つのパスとみて、2つの端点を2次元dpのキーにするやつ。復元が要求されていてキレそうになりながら書き直した。

Hは、最初に辞書順を考えずカウントして、後からS未満とTより大をそれぞれ取り除いた。よく問題文を見るとS\le Tとは書いていなかったので僕の提出は落とせそう。取り除き方は、Tを考えているときは文字の辞書順を逆転させることで、両方「未満」として扱える。計算についても、例えば先頭文字で大小が決まらない場合は次の文字……と見ていくと、どの文字を選ぶかはだんだん固定されざるを得なくなっていくので、線形時間で計算できる。Eは\sqrt{-1}が存在するような素数Pを選び、(x,x\sqrt{-1})(x\sqrt{-1},-x)を入れていくことで、値の積和についての条件は満たせる。あとはこのペアを9個作れば29=512本の数列ができて、答えの1つとなる。

Cは結構最初のほうに読んで不可能だと諦めたのだが、コンテストが2時間も経過してみたらかなり通されていた。読んでみると、M\le Nであることに気づいた。つまりグラフが木かなもりの場合しか考えなくてよいということで、どうとでもなる。M\le\min\left(\frac{N(N-1)}2,N\right)と書かれると、途中まで読んだ段階で2\times 10^5とminを取っていると自分の頭が勝手に補完してしまうので、惑わされた。残り時間はIを考えながらTwitterを見ていた。30NQでは解けた気になったが、定数倍が重すぎて通らないだろう。解説を読んだ感じ、30NQの考察も間違っていそうな気がする。

ECR25のEFを解いた。Gは放置。

Dashboard - Educational Codeforces Round 25 - Codeforces

Eはちょっと前から開いて数度考えていた問題。辞書順最小を求めるので当然前から貪欲だと思っていたが、正しく求めようとすると計算量が抑えられない。試しに後ろから貪欲を考えてみると、辞書順最小が得られることが示せてしまった。ちょっと前のABCで後ろから貪欲する辞書順最小の問題があった気がするが、その時一般には成り立たないことが何度も言及されていて、それで後ろから見ることに恐怖心を抱いていたのかもしれない。FはZ-algorithmとdpで、dpの遷移先を決めようとループするとO(1)では遷移のコストを求められないが、遷移に使う部分文字列を決定して遷移先を2回以上見ないようにすると計算量が落ちる。

あまりにも眠いので午後6時くらいに布団に倒れこみ、そのまま6時間も昼寝をしてしまった。起きた時には日付が変わろうとしていた。

ECR26のA-Fを解いた。Gはこれまた放置。

Dashboard - Educational Codeforces Round 26 - Codeforces

Aはよい。Bは3つの文字が異なることをチェックしておらず1WA。Cはif文を書きまくる。Dはbool値dpを考えてしばらく悩んでいたが、元の次元を1つdpの値に入れるとよい。最大値を保存する。Eは、f再帰的に呼び出されるごとに\gcd(a,b)が小さくならないことがわかるが、実装には特に関係ない。x素因数分解して、今以降で最初に\gcd(a,b)\gt 1となるまでの操作回数を計算する。1回でyは必ず半分以下になるので、計算量的に十分間に合う。Fは、まず先頭の0を全部取り除き、残りの数列の長さが4以上の場合はシミュレーション。2と3の場合は、値を式で表して二分探索なりする。

次にECR35のFGを解いた。このコンテストは僕が4年近く前にリアルタイムで出たもので、upsolveをしていないためFGが残っていた。

Dashboard - Educational Codeforces Round 35 (Rated for Div. 2) - Codeforces

Fは難しいが、適当に直径を取ってみたら解けた。直径を残すように葉を削除していくと、すべての葉が最大の長さで削除できるため、よい。Gは置換の様子をarray<short,100>で持ったら2995msで通った。高速入出力を貼って遅延セグ木から双対セグ木に切り替えると1060ms。解説を読むと、普通のセグ木に置換の合成を乗せて、クエリをソートして端から見ていくことで毎回全部の置換の合成が得られるということらしいが、実装したら1169msだった。

以上でCFにおけるここ1年間のAC数が1000に到達した。最近はこれを目指していたため、達成した今何をするべきかがわからない。

TwitterVSCodeのデバッガの導入ができないというツイートが流れてきたので、VSCodeをほとんど使ったことがないくせに首を突っ込んでみた。最初はTwitterのリプライでやり取りを交わしていたが、途中からさすがに面倒になってGoogle Meetで画面共有してもらいながら進めた。サークルメンバーなのでその辺りの障壁は低いはず。

どうやらQiitaの記事から拾ってきた設定ファイルがWSL向けに書かれている一方で、環境がWindowsのままらしい。いろいろ調べてみたが、結局Remote WSLを導入してもらうことになった。Qiitaの記事ではSSHログインだのなんだの書いてあるが、特に必要はなさそう。というのも、結局WindowsディレクトリとWSLを連携させようとするから小難しいことをしなければならないのであって、最初から全部WSL側でやってしまえば特に問題ない。これまで書いてきたコード辺をエクスプローラ経由でコピーしてもらい、あとはターミナルで良しなに操作してもらうことになる。デバッガ起動についての設定も、ACLのインクルードのために毎回-Iオプションを渡すことさえファイルに書いておけば、Qiitaの記事からコピペしてくるまでもなかった。これで動くようになって一安心。自動で生成されたファイルはできるだけいじらないのが一番良いと思っている。

ラノベを1冊読んだ。「神々の権能を操りし者」。自分の実力を隠している主人公という前フリが琴線に触れたので購入した。1巻から実力を周囲に知らしめていて、手っ取り早い満足感があった。しかし2巻以降はどういう展開になるのだろうか。なろう原作で、なろうのほうではもう文庫数巻分連載されていそうだが、そちらを読むほど気に入ったわけではなかった。

別のラノベに手を出そうとしたが、明日は夕方から1on1があるし、そもそも何も進捗が産めていなくてまずい。焦りながら午前10時、就寝。

09/24(金)

午後2時起床。昨日シャワーを浴びずに寝たせいか頭皮が痒くて仕方ない。急いでシャワーを浴びた。原付に乗って購買に行き、注文した本を受け取った。今週火曜日の日記で言及した、届いていなかった1冊。重版待ちだろうかと書いたが、確認すると初版だった。

帰ってきてから1on1まではコーディング。最低限の進捗を産んで、何とか報告する内容ができた。最近、悪い意味で1on1に慣れてきたのか、報告と称して特に纏まっていないことをグチャグチャ喋っているだけになってしまった気がする。他の人の1on1を録画で見てみるべきなのかもしれない。少なくとも、今の報告の形態は、相手への甘えが多分に含まれていたと自省している。ともあれ進捗は進捗で、この先やることもこれまでと変わらず決めることができた。今日はあっさり目に終了。

自分の評価しているラノベの続刊が出るのかどうかを常々気にしていた。今日、BOOK☆WALKERというサイトにラノベランキングが日間・週間・月間で出ているのを見つけた。ここは判断の要素として十分だろう。ちょっと眺めていたが、精霊幻想記の既刊が軒並みランクインしていてびっくりした。アニメ化・ソシャゲ化はかなり広告効果があったということだろうか。個人的には、ニコニコ動画で出てくる謎解き風広告の答えがキャラクター名なのはまずいんじゃないかと思っている。そんな固有名詞を答えにするのは、ダメだろ。

bookwalker.jp

しばらくラノベを読んでいたが、午後9時20分からyukicoder 315に出た。全完。

yukicoder contest 315 - yukicoder

Aはよい。Bは得点がiであるという部分をちょっと誤読して時間を取られた。最適な戦略が常に同じだろうと予想していたがそんなことはない。CはDP、DはbitDP、EもbitDP。この3問はほとんど自明。Fは無限場合分けで、その時かなり眠かったのもあり厳しい思いをした。幸い一発で漏れなくパターンを列挙することはできていたようで、あとは場合の数や係数を修正していたらサンプルが合い、通った。特に、一番最初の実行からサンプル1でほとんど正解の値が出たのがやる気に繋がった。

「クラスの大嫌いな女子と結婚することになった。」3巻を読んだ。非常に面白かった。テンポのいい掛け合いが小気味よいと思っていたが、もしかして漫画原作ということが関係しているのか?漫画は読まないので、どのくらいのペースでそういう掛け合い・ギャグが挟まるべきなのかを知らないが、とにかくラノベであまり見ない感じのテンポであることは確かだ。内容についても非常に満足感がある。2人がそれぞれ空回りしている様子は辛かったが、それらの描写があってこそラストシーンが光る。報われた気持ちになった。新キャラが出るようで4巻への引きは不穏だったが、楽しみ。

次に「転生ごときで逃げられるとでも、兄さん?」2巻を読んだ。めちゃくちゃ面白かった。紙城さんは、今のところ代表作「継母の連れ子が元カノだった」で恋愛もののイメージが強いが、個人的にはバトルシーンの爽快感や見せ場の作り方が好み。書籍化作品では他に「最強カップルのイチャイチャVRMMOライフ」もバトルシーンがあって好きだったが、こちらの続刊は……過去の売上ランキングを調べた感じ、望み薄か。そもそも著者がシリーズを複数抱えていて超多忙だろう。また、恋愛ものでもバトルものでも、ところどころにミステリのエッセンスが加わっていて、それがまた面白いのだ。今回の巻では特に学園・順位戦・闘技場でバトル、とテンプレ設定が余さず盛り込まれており、間違いのない面白さだった。

日記を書いてからちょっとコードゴルフをしようと思ったが、全然縮まない上に画面を見ているつもりでしばしば意識を飛ばしてしまったため、諦めて布団に入った。午前7時就寝。

09/25(土)

午後0時半起床。眠気と戦っているうちにACPC2021 day2が近づいてきてしまい、昼食のために用意したパックご飯やみそ汁を食べられないままコンテストに突入した。30分ちょっとして一段落した頃合いにようやく食べたが、冷えていて悲しい気持ちになった。その頃はコンテストでも冷えていたが、最終的には10完9位と、ギリギリ面目を施せた気になっている。順番はABCDEFGIKH。

https://onlinejudge.u-aizu.ac.jp/services/room.html#ACPC2021Day2

Aはよい。BはT_i\le 3000の制約からP_iも小さいものだけ考えてよいことを導くと、2次元dpができる。昨日に引き続きFAだった。Cは線分と点の距離を求めるだけなので幾何ライブラリにある……が、誤差が怖かったので整数の範囲で計算を行うライブラリを持ち出してみた。結果、verifyしていなくて式が違う上にオーバーフローしており、2WAしてC++で通すことを諦めてRubyを書いたが、typoでさらに1WA。合計3WAも出してしまった。聞いた話によると、どうやら普通にlong doubleで通るらしい。何のための問題だったんだ……。DはA_iでソートして実家dpをした。

Eは難しかった。タイプ1のクエリはオイラーのφ関数そのまま。タイプ2が問題だった。結局、1\le Z\le NX_iと互いに素なものを求めてφ関数の値を引くことにした。互いに素なものを求めるのは、square-freeにして包除でできる。計算量が怖かったのでメモ化しておいた。Fは二分探索やるだけ。Gは木でk個上の祖先が欲しくなったが、これはdfsで潜るたびにvectorにpushして、上がるたびにpopすると得られる祖先リストで求まる。Iは同じ人を含むサークル同士に辺を張ると重み付き最大安定集合になり、半分全列挙で解ける。

Kは腕前をどれだけ上げるかを決め打つという発想で、まず各ステージについて手動でクリアするレベルとそれに必要な腕前を計算しておき、腕前の値で降順ソートして、どのパターンでクリアするかを変化させながら計算する。これは優先度付きキューに入れて、腕前をだんだん落としつつ足りなくなったらパターンを切り替えるという方法でシミュレートできる。Hは2次元セグメント木で、0の処理が怖かったので書き換えた場所の4近傍も構築するようにしたら2.79secで通った。実装は↓のページを参考にしたが、updateの時にちゃんと下2つの値を見るように書き足す必要があった。

blog.hamayanhamayan.com

今日はCodeChefのコンテストがあるらしい。先週気になっていると言ったばっかりだし、また今日はコンテスト尽くしの1日にしてみようという思いから、アカウントを作った。練習問題を3問ばかり解いて、どんな感じなのかを探る。main関数の型がなくてもCEにはならず、longは64bit整数らしい。

最近いろんな人がCodechefに出るようになっている。最初出会ったときに謎インドコンだと思って敬遠したっきりなのだが、やっぱり自分が出ていないコンテストがあるとちょっと焦燥感がある。今からでも始めるべきかもしれない。

週記(2021/09/13-2021/09/19) - kotatsugameの日記

新しいラノベを読み始めたが、そこそこで置いておいて、先に食事やシャワーを済ませておくことにした。今日は朝の5時までコンテストがあって、次の日の午後1時からもまたコンテストがあるからだ。

午後8時になって、ARC127に出た。ギリギリで5完して24位。

AtCoder Regular Contest 127 - AtCoder

Aは1,11,111\dotsそれぞれについて数える。数える方法もちょっと考え込んだが、桁を決め打てばそれぞれ単純なminで求まる。Bは難しい。tの先頭1文字が2であることは確定する。そのあとはできるだけ0を置きたいので、N\le 3^kなるk\ge 1を取って、後ろk桁を弄る(0\dots N-1を3進数と見て展開した)ことでN通りの文字列を作ることにした。無事N通りの文字列が作れたら、それらの先頭に2000...を足し、012を適当に巡回置換することでもう2N通りも得られる。作り方から各桁の文字の分布についての条件が満たされる。

Cも……難しい。先頭の桁から決めていくと、1を置くときは2のべき乗だけ辞書順で大きくなるらしいことがわかる。これはXの対応する桁から1を引けるかどうかで判定可能。0を置くかどうかを判定するため、Xをデクリメントする必要がある。デクリメントは106回くらい行われる可能性があるが、そう何度も上のほうの桁まで見に来ることはないと考えられるため、愚直にやっても間に合う。これに関連して、maspyさんの「next_permutationを105回呼んでも問題ない」というツイートが興味深かった。

Dは、まず1\le i\lt j\le N1\le i,j\le Nに緩めてもよい。最終的に出てきた答えを2で割れば正しい値が求まるからだ。そうして、各(A_i,B_i)のペアについて、相方となる(A_j,B_j)がどんな値であればどこの桁で大小関係が定まるのか、を全探索する。大小関係が決まる桁より前はA_i\oplus B_iA_j\oplus B_jが一致するので、これをキーに使えばペアの情報はかなりまとめられる。まとめた値をvectorなどに溜めておく。次に、逆に(A_j,B_j)を全探索して、先ほどまとめた値とXORを取った和を計算する。これは事前に桁ごとに立っているbitを数えておけば計算できる。計算量がk=18としてO(k^2 N)で、2secくらいかかったが、問題なく通った。

Eも難しかったが、何とか解けた。連続するpopを、その前のpushと組み合わせて見る。もしpushがpop以下であるようなら、どんどん前に遡っていって、必ずpop>pushであるようにしておく(後で見るように、これは不可能な場合があった)。こうすると、popが組になっているpushより前の値を壊してしまうことがなくなる。ある特定の集合を作れるかどうかは、小さいほうから順に「集合に入っている→push」、「入っていない→pop」に対応付けてみて、pushと直後のpopの大小関係が壊れていないことを確認すればよくなる。popと次のpushの大小関係は問題ではないため、そこに自由度がある。ここで、「現在の集合に入っている要素より大きな値をpopしたのが何回か」をキーにして、そのpopの間に埋め込むようにpushするdpが考えられる。

実装したらサンプルが合ったが、残念ながら計算量がO(N^3)になってしまった。しかもdp遷移にcombinationが出て、高速化できそうもない。そこで、先ほどまとめたpushを分解することにした。最初はpopも分解しようとしたが、以前の値を壊してしまわないようにまとめるのが本質だったようで、全然答えが合わなかった。pushだけバラバラにしてみると、先ほどのcombinationはpushに対応するものだったから、1個ずつ考えているということで消え、後にはただ範囲加算のみが残った。これは容易にO(N^2)に落とすことができる。

提出したらWAとREが出た。焦りながらコードを確認した感じ、popをまとめている部分しかREが出そうな箇所がない。努めて冷静に考えると、一番最初まで遡ってもpop=pushとなってしまう場合を見落としていることに気づいた。うまいことemptyのチェックを挟んで書き直し、サンプルを試さずに投げたらAC。コンテスト終了3分前だった。

直後にCodeChef。今日はLunchtimeという種類のコンテストの9月号らしい。初参加なのでdiv.3。当然のように優勝した。レートは初期値1500→1766(+266)。

https://www.codechef.com/LTIME100C

VDATESはよい。TWODISHは全探索。UNQEQはNが4の倍数でないと総和が2で割れず、逆に4の倍数なら構築できる。(1,4)(2,3)のように組み分けするのを繰り返して2つの数列の総和を等しくできる。この時、prefixの総和の差を広げるような要素を優先的に配置すれば、途中で差が0になることはない。SOD3は自明。

ここからはdiv.1と問題が共通らしい。ALBOFACEは、最初にメモ化再帰を書いたらTLEしたので、grundy数を考えることにした。手計算で小さい値を調べていたところ、遷移の自由度がほとんどないことに気づき、計算方法も思いついた。2進表記にして、連続する0をまとめて考えると、上位桁から順にgrundy数を考えていける(冷静になるとgrundy数ではなく真偽値でよい)。INTREPはしばらく詰まっていたが、2\mid Nならば(2N,N)が答えになることに気づいて解けた。2\not\mid Nであった場合は、奇素数pであってp\not\mid Nなる最小のものを探し、(pN,(p-1)N)が答えになる。p-12pより小さい奇素数の積なので、\frac{p-1}2\mid Nが従う。またそのようなpp\lt 100に必ず存在するので、出力の制約も満たせる。

以上6問がdiv.3の問題だったが、それ以降の問題も解けはするようなので、解いていた。SUBLCSは選択したペアの位置も含めた一致を答えるのだと思って何度もWAを重ねた。単純に各値が連続して何度出現できるかを見ればよい。RARRAYは尺取りをする。後ろから前に戻ってくる感じに実装して、前に1つ進めたとき新たに考慮する要素が順序を壊すようなら、考慮しないようにもう一方の端を前に進めてくる。順序を壊す判定はセグメント木で、値→インデックスとインデックス→値を両方区間minで持つ。謎の勘違いを繰り返し、これもたくさんWAを出した。最初のコードはACしてから見ると何を考えていたのかと呆れざるを得ない。MXMNSSUMは答えが負になる場合の処理ができず解けなかった。bitsetでできるなあと思っていたら、立っているbitが区間になるらしい。

div.3の全完には1時間かからなかったが、結局そこから2時間みっちり問題を考えていた。今日最後のコンテストまで1時間あったので、その間に日記を書いていた。午前2時からFHC R2に出た。

Facebook Hacker Cup - 2021 - Round 2

ABcCを通して59位。R3進出、Tシャツ獲得に加え、上位200人なのでTシャツが何か特別仕様になるはずR3の上位200人に対する褒章らしい。ぬか喜び……。

Aは難しそうな見た目をしているが貪欲でいい。マッチングにあぶれた人たちは着替える必要があるが、その時まだ着替えたことがない人を優先的に使う。そうしない場合に比べて損をしない、という事実が初回から順番に成り立っていく。Bは各辺ごとに同じ周波数の2頂点を分割しているかをチェックする。部分木の周波数をカウントして全体の個数と比較することにすると、マージテクで全ての頂点に対して計算できる。スタックオーバーフローが怖かった(どう考えても再帰dfsしたら落ちる制約だった)ので、最初にBFSしてその逆順にループを回し、再帰関数を使わずに計算した。

cは、1つの車を消す操作は最後にまとめて行ってよいこと、上と下にずらすのは片方しか行わなくてよいことがわかるので、あとはずらす幅を全探索。基本的に、ずらしすぎて開けたい列まで埋まってしまった場合を検出すればよいが、ちょうど開けたい列に車をずらしてしまった場合もケアする必要がある。

Cはこれの1点更新。簡単のため、上にずらす場合だけ考えて、下にずらす場合は盤面を反転させて対応することにした。ある場所に車が増えると、「ずらしすぎて開けたい列まで埋まる」場合のずらし幅が少なくなる。列の車の場所をsetで管理しておくと、今のずらし幅に対応する車が必ず存在して、その1個上の車になる。ということで、対応する区間に1加算すればよい。車が減る場合も同様。ずらしたときにちょうど車が来てしまう場合の1点更新も含め、遅延セグメント木で処理できる。解法を思いついてからしばらくはやりたくないと駄々をこねていたが、実際書いてみるとなかなかシンプルになった。それでも2000Bを超えているが。

今日は3h+2h+3h+3hで合計11時間コンテストに出ていた。立派な競プロ戦士になれた気がする。日記を書き上げて午前6時半就寝。

09/26(日)

昨日と同じく午後0時半起床。さすがに疲れがひどいが、昨日の経験から布団の上で眠気で戦っていると食事できなくなることがわかっていたので無理やり身を起こす。カロリーメイトと冷蔵庫にあったフルーツを手早く用意したが、フルーツだけ食べたらコンテストの時間になってしまった。

午後1時からACPC2021 day3。今日はABDCEFGの7完8位。難易度順らしかったが、それよりはsolvedを見て解いた。結果F問題までは爆速で6完最速だったが、G問題で勘違いを繰り返してしまい爆発した。

https://onlinejudge.u-aizu.ac.jp/services/room.html#ACPC2021Day3

Aはどうにでもなりそうだが、ちょっと怖いので丁寧にやった。Bは素因数を数えて2で割る。Dは頂点を追加しながら期待値を求めればよい。CはBをブロックに分けてAと対応付け、そのブロックの作り方を考える。1より大きな要素がブロックに2個以上存在するなら0通り、1個存在するなら左右の順番でcombination、0個なら真ん中をループで決めて1個の場合を足し合わせる。特に3番目の場合分けはちゃんとやると2のべき乗になるらしい。ブロックごとの操作列を組み合わせる時もcombinationを考える必要があることを見落として1WA。

Eは昨日のFHC R2D(の解法ツイート)で見たばっかりで、先頭24個を取り出して全探索すると鳩ノ巣原理から必ず見つかる。Fは怪しげな操作をしているので適当に累積和を取ったらswapになった。つまり累積和の転倒数。一瞬で解けて有頂天になりながら出したら、末尾の要素を変更できないことを見落として1WA。

Gは難しかった。サイクル基底かと思ったがそんなことはない(一般に頂点属性でサイクル基底はやりにくそうだ)。もっと自由な操作ができる。具体的には、いったんGまでたどり着いてから「任意の頂点uに行く→戻ってくる」を繰り返すことで、c_G\oplus c_uをコストにXORすることができる。これを2回セットにすると、任意の頂点2つを選んでXORすることに言い換えられるから、適当にc_0をほかのc_uにXORした状態で基底を計算し、SからGへの適当なパスのコストにXORして最大を求めればよい。パスを求めるのはdfs木とLCAを使ってやった。

……WA。手元で作っていたグラフを眺めていると、SGパスに含まれる辺の本数の偶奇を任意に定めることができた場合はさらにやりたい放題できることに気づいた。上で頂点2つをセットにする必要がなく、最大値を達成するような頂点たちが決まったら、それに沿うようにパスの本数の偶奇を定めればよい。二部グラフ判定を書き加えるとようやくACできた。結局5WA出してしまった。

さて、これでACPC2021の全日程が終了した。今年はオンライン開催で、僕は3日間ともソロ参加かつ、3日間ともボス問題だけが倒せなかった。大学の合宿のボス問題を自分が解けるビジョンが見えないが、昨年の日記(この日記は1年以上続いているので去年の同時期のことが読める!)を読み返した感じ、椅子を温めていない時間は長くなっていそう。

ちょっと食事をした後、午後5時からOpenCupに出た。チームで5完。

最初30分くらいdiv.2の問題ページを見ているというハプニングがあったが、幸い気づくまでに自分が読んだ問題(A-C)はどれもdiv.1と共通の問題だったので、助かった。div.2の順位表を見て、Aは解けなそうと思っていたのに、div.1の順位表ではバカスカ通されていてたまげた。まごまごしているうちにチームメイトが瞬殺したので、実装もしてもらった。連続する正の数を3つ以上足すと素数にはならない、というのは超最近のyukicoderで見たばっかりなのに1ミリも頭に思い浮かばなかった。疲れている?

No.1657 Sum is Prime (Easy Version) - yukicoder

そのあと、B問題を念入りに詰めて、solvedが1桁のころに通すことに成功した。ギャグではない問題を通したのは初めてかもしれない。自分が行動できる回数は高々\sqrt{H_0}種類くらいしかないので、全探索する。そのあとは丹念に場合分け。2次関数の(整数としての)最大値を何回も求める必要が出てきて、ああ……終わった……と感じたが、試しに平方完成して睨みつけてみると、それらによって得られる値が答えに全く影響しないということが分かった。実数範囲に制限を緩めて考えると、たくさんの最大値「の」最大値が直ちにわかって、ほかのケースで考えている値と本質的に一致あるいは小さくなるためOKという感じ。サンプルが合わなくてドキッとしたが、ちょっとした範囲のミスで、エイヤと直して投げたら1発で通った。

E問題が飛んできたので考えてみる。チームメイトの残した考察があまりピンと来ていなかったが、ACした後に見ると大体同じことをやっていたように思える。連続する同じ扱いの値を纏めると考えやすくなって、下から貪欲……と思ったらWAを出した。合計3回くらいWAを出していたら、さっきまでE問題を考えていたチームメイトがコードを読んでくれたらしく、Hackケースを教えてもらった。それで何を抜かしていたのかに気づき、AC。助かった……。

他の人がいろいろ実装している間にJ問題を考えていたら、それなりによさそうな性質を見つけた。パソコンも空いたので実装するか、と思ったが、入力を受け取ったあたりで思ったより実装がヤバいことに気づく。このとき午後8時半を回っていて、ABCまでそんなに時間がなかったのもあり、焦って考えが全然まとまらない。結局ABCまで残り10分くらいになったところで逃亡してしまった。

AtCoder Beginner Contest 220 - AtCoder

7完97位。Fまではそれなりにいい調子だったのに、Gで8WAして何もかもが台無しになった。

Aは\left\lfloor\frac B C\right\rfloor Cで解いた。dc。Bを開いたらあまりにもdc向けの問題すぎてたまげた。自明な5Bコードを書いて提出し、順位表を見に行ったところ、dcを書ける人がすでに通していたため、絶望。CからはC++。適当に和で割って残りをO(N)……と思ったらWA。問題文の不等号が等号なしだった。Dはdp。Eは上って降りる幅を全探索し、それぞれを気合いで計算した。サンプル1が合わなくて大変だったが、一度合ったらそのままACできた。Fは全方位木dp。

Gは、まず線分を全探索して傾きでグループ分け。この時点で答えを求めてしまい、サンプル1が合わないのを見て、等脚台形という条件をすっかり忘れていることに気づいた。等脚台形にするためには、2つの線分の中点を結ぶ線分が元の線分に直交する必要がある。ということで、傾きでグループ分けした中で中点(を適当に移動させて正規化したもの)でさらにグループ分け。重なる線分を選ぶとまずいので、中点も一緒に持っておいて判定する。最後に各グループに対して答えを求める。……WA。かなり面倒なコードを書いたので、解法ミスではなくどこかにバグがあるのだろうと思って探す。数か所ミスを見つけたものの、それらを直して提出したつもりなのに、最初の8WAから一歩も先に進めない。残り20分を切ったころ、大きいほうから2要素を持つ変数の初期値が-2\times 10^9だとマズいことに気づいた。これだと、10^9が2個あったとき、組になって答えが0で更新されてしまう。これを-2\times 10^9-1に直したら通った。重みは2つまとめるところまではint型に収まるな、と思ってわざわざint型を使ったのが裏目に出たらしい。適当に-10^{18}とかにしておけばよかったものを……。

コードゴルフ。Aはコンテスト中のdcコードが最短。Bも5Bコードで、こちらは案の定提出時間で負けていた。CはRubyで書いてからdcで縮めたが、僕がdc 50Bを作って出したころには44Bが提出されており、完敗。しばらく睨んでも縮みそうにはなかった。DはRubyで書いて負け、Perlで縮めたがそちらでも負けた。以上前半4問のうち1問しか最短を保持できていない。最近コードゴルフが盛んで負けまくり。

Hを通した。半分全列挙で、2つの集合STの間をどうするかが問題。コンテスト中は時間がなくて全然考えられなかったが、じっくり取り組んでみると、Sで「選ばなかった頂点」の組から、Tの「選ぶと監視されている辺の本数の偶奇が変わる頂点集合」が求まることがわかる。今度はTの選び方を全列挙して、先ほど求めた頂点集合との共通部分の要素数を見たい。これは、現在監視されている辺の本数の偶奇に対してSから作ったTの頂点集合とTの選び方をそれぞれカウントしておき、2×2通りAND畳み込みをすることで計算できる。

H問題で面白いコードがあった。1900msくらいかかっているので想定TLE解法だろう。まずすべての頂点を選んだ状態から初めて、ある頂点を監視するのをやめたとき、隣接するより頂点番号が大きな頂点それぞれに対してフラグの状態を変える。これは隣接行列の行をXORすることで計算できる。逆に、フラグが立っている頂点を監視するのをやめたとき、「隣接するより頂点番号が小さな頂点のうち、奇数個がすでに監視されていない」ことがわかるので、それらとの間にある辺は監視されなくなり、監視されている辺の本数の偶奇が変化する。今見ている頂点、現在監視されている辺の本数の偶奇、各頂点のフラグの3つでdpを行う。3次元目の値はmapで扱う。

atcoder.jp

この解法でコードゴルフするとかなり短くなった。mapを使うのに#import<map>とすると、入出力のライブラリが使えないので困る。そこで#import<regex>とすると、2B増える代わりにC言語由来の入出力関数が使えるようになる。mapを使う場合はこれかbits/stdc++.hしかないと思っている。

ラノベを1冊読んだ。「精霊幻想記」20巻。最近やっていた話が一段落する巻だと思っていたら、ラストに衝撃的な展開があり、まだ心の整理がついていない。またそれに向けての加速だったのか、最後のほうは展開が目まぐるしくて狐につままれたような気分だ。主人公・リオはこれからどうなってしまうのか……。次巻を怖がりつつも楽しみにしている。

週記(2021/09/13-2021/09/19)

09/13(月)

週記を投稿してから布団に入り、しばらくハーメルンを読み返して寝た。午前9時前だった。先週金曜日の1on1でこの先しばらくやることを確認したと書いたが、結局それから1ミリも進められなかった。

午後3時に起床。15時と午後5時を見間違えたこと、寝ている間に月曜日のミーティングの時間が1時間早まっていたことが合わさって、ついに寝坊してしまったかと冷や汗をかいて飛び起きた。セーフ。

せっかく起きたのでミーティングまでしばらくインターンの業務を進めた。それっぽいコードは書けたが、途中でエラーが出る。サンプルコードをほとんど写したようなものだったが、やはり自分で実行していないコードということで何か勘違いがあるらしい。自分で解決できないこともなさそうだが、設計まで含めて1on1で聞くのが早いだろう。

ミーティングは特に何事もなく終了。今週から自分もスライドを用意して、先週何をやったかと今週何をする予定かをきちんと発表した。来週月曜日は国民の休日らしく、ミーティングが別の日にずれるらしい。そういうこともしっかり考えてるんだなあという気持ちになったが、逆にしっかり考えないと会社としてはまずいのか。

学食に行って帰宅。土曜日に注文したモニターアームが届いていた。思ったより重くて、机の耐荷重が大丈夫か……?という気持ちになる。ダイニングテーブルは奥行きもあって広いが、一方でパソコンデスクほど耐荷重が重くないのが難点であると気づいた。

しばらくハーメルンを読んだりコードゴルフをしたりした後、CF ECR18を埋めようとした。Fはまだ解けていない。

Dashboard - Educational Codeforces Round 18 - Codeforces

Aはよい。Bは難読。特に問題文中の例はゲームの途中から書かれているため、理解するのに苦労した。わかってしまえばシミュレートするだけ、実装は何とでもなる。CはABC182-Cの強化版で、数字に0が含まれること、桁数が105オーダーであること、復元が求められていることから非常に難しく感じた。ABCの方と同じく場合分けをして解こうとしたが、ふとただの桁dpで解けることに気づいた。Dはbitを見て適当にやる。

C - To 3

Eは難しい。各集合の大きさをnn+1であると定めると、必要な条件は\exists q\;s.t.\;qn\le a_i\le q(n+1)と書ける。ここで\left\lfloor\frac{a_i}{q}\right\rfloorはそんなに種類がないので、適当にiを選んで\left\lfloor\frac{a_i}{q}\right\rfloor\left\lfloor\frac{a_i}{q}\right\rfloor-1を全部調べればよい。各na_iに対して最適な分け方は上の条件から出る。

インターン先から届いたパソコンのセットアップを済ませることにした。起動してみるとWindows単体が入っていたので、Ubuntuとのデュアルブートにする。頑張ってマザボの例のアレ(ファームウェアインターフェイス)を起動すると、BIOSではなくUEFIだった。マウスによる直感的な操作でいろいろ調べてみると、HDDのところにUbuntuと書いてある。しかしWindowsのほうから確認したら全ての領域にアクセスできていそうなので、すでにデュアルブートになっていたとかいうことはないだろう。聞くところによると、このパソコンは以前Ubuntuとのデュアルブートだったのを、僕に貸与するにあたってわざわざほぼ工場出荷時の状態に戻してくださったそうだから、その時残ってしまった名残なのかもしれない。以前別のパソコンで使った、Ubuntu 20.04インストール用のUSBを差し込み、起動の優先順位を変更していざインストール。

画面上部に1行だけ映っているメッセージで検索すると、どうやらグラボが入ったPCにUbuntuをインストールするときにドライバがないため起こる現象らしい。確かにオンボードでないGPUが入ったパソコンにUbuntuを入れるのは初めてだ。しかし解決方法が設定ファイル編集によるものらしく、なんだか怖かったのでとりあえず無理やり電源を落として再起動してみると、「Ubuntu (safe graphics)」といういかにもそれっぽい起動オプションが増えていた。それを選んだらちゃんとインストール画面まで進めて感動。デュアルブートを選択して、パーティションも特に弄らずインストール開始。

失敗したというメッセージが出た。Ubuntuにバグレポートを送信すると、既知の問題だった。ブラウザでそのバグのページが開いたので読んだところ、インストールのオプションで「サードパーティー製ソフトウェアをインストールする」にチェックしていると起きるらしい。GPUのドライバはどうするんかいな、と思いながらチェックを外して再度試みると、今度はどうやらうまくいったようだった。

ソフトウェアとアップデートから適当にGPUのドライバを入れる。これにも失敗したという表示が出たが、終わってみるとなんだかいい感じになっているようなので、放置。最後に、Pythonの開発環境を整えて、GPUで計算できるようにする。わざわざUbuntuを入れたのは主にはこのためで、WSLからGPUを使うにはWindows Insider PreviewからWindowsのバージョンを更新しなければならなかったりして、かなり敷居が高い。やってみたらUbuntuを入れるのも敷居が高かったのだが……。

Pythonの開発環境を整えること自体はよくある話なので、適当にQiitaから記事を拾ってきてその通りに進めた。途中でAnacondaを使い始めたので、pip派の自分はそこで分かれる。Ubuntu 20.04はデフォルトで入っているPythonのバージョンが3.8と別に古くもないため、その辺りはデフォルトのままでいい気がしている。特に苦労することなくtorch.cuda.is_available()Trueを返すようになった。

せっかくパソコンをセットアップしたので、これまでWindowsで動かしていたPythonスクリプトを一通りUbuntuでも動かしてみることにした。すると出力が一致しない。なんとなく理由の予想はつくので、また1on1で聞いてみることにしよう。ところで、机の上にキーボードが2台あって、片方でUbuntuを操作してもう片方でWindowsを操作している。かなり誤爆しやすいことが分かったので、十分気を付けなければならない。

これで今日の作業は終わり。シャワーを浴びて布団に入り、本を1冊読んだ。「かくりよの宿飯」7巻。6巻を読んでからハーメルンにハマってしまってちょっと時間が空いた。しかしやはり面白い。僕が好んで読むネット小説とはまた違うタイプの面白さで、たまにはこういうものにどっぷり浸かるのもよい。巻数的に、いよいよクライマックスにつながる流れの中にあるようだ。大旦那様が姿を消してしまい微妙に張り合いがないが、再会を楽しみに読んでいきたい。

午前7時半就寝。

09/14(火)

午前11時くらいにふと起きたところ、ちょうどモニターが届いた。しかしあまりに眠いので放置してまた就寝。次に起きたのは午後3時だった。日本橋ハーフマラソン(増刊号でないほう)で学生15位入賞していたらしく、アマギフを5000円もらった。

今日は丸一日使ってパソコン回りを整えなおす。まず手始めに机の周りのものをすべて取り外し、掃除をした。土曜日に買ったエアダスターが大活躍したが、逆に酷使しすぎて気化熱・断熱膨張によって缶の温度が下がり、結露どころか雫が凍り付いていてびっくりした。

ルーターも取り外していたのだが、実は今日は午後5時半から1on1が予定されていた。直前になって全然準備できていないことに気づき、とりあえずネット回線だけ元に戻してノーパソから参加した。コード類は一応GitHubに上げてあったので何とかなったが、画面共有の時に1画面しかないと、脇で見せる資料を準備するみたいなことができないため、非常に不便だった。使うモニターの枚数は、ひとたび増やすともう減らせなくなってしまうことは有名。

1on1では昨日のコードの動かない点を聞いて解決することができた。また、WindowsUbuntuで出力が食い違う理由もかなりそれっぽいので、一度対処法を試してみることになった。予想がついていたのなら先に試しておくべきだったかもしれないが、今日はパソコン回りを整える日にしていたので、1on1までにそのような時間はなかった。

1on1が終わって、また掃除に戻る。とりあえず一段落して、今度は機器を戻したり取り付けたりする。モニターアームの取り付けは机の後ろに回ることができないとなかなか厳しいものがあるため、机をずらし、まずそれを組み立てて取り付けた。地震が怖いのでネジを閉めるときはできるだけギュウギュウにすることを心掛けた。一か所プラスドライバーを自分で用意しなければならないネジがあったが、1年生の春に家具の組み立てで使ったものが残っていて助かった。

モニターアームを机に立て、モニターの高さを調節しつつ取り付ける。2台あるので、高さや角度を揃えようとしたのだが、ネジを緩めたり閉めたりして高さ・左右の角度を調節するタイプのものだったのでなかなか苦労した。最終的にはちゃんといい感じにできたので、机を壁に寄せ、あとは机に置くモニターを設置し、ケーブル類を全部パソコンに接続して完了。コンセント2口それぞれに6口ある延長ケーブルを差しているのだが、モニター5枚・パソコン2台・プリンター・ルーター・謎の機械(PLCアダプター?)・デスクライト・USBハブでちょうど全部埋まってしまった。そのほか様々なケーブル類は一切まとめていないため、机の下はすごいことになっている。

机の上はこんな感じ。

非常に良い。前々から、モニターを縦に積んで上の画面を微妙に下に向ける配置、その角度にあこがれていた。視界を覆うようなモニターたちよ!これぞロマン!何に使うかは考える必要がない、何故なら、モニターはあればあるほど良いため。

しばらく実際に使いつつ、インターンのコードを書いていた。まず、画面が遠くてよく見えないため、Ubuntuの設定で大きな文字を使うようにした。またターミナルではフォントサイズもちょっと大きくしてある。椅子の配置の問題かも知れないが、右上のモニターを見上げるのが一番首に負担がかかると分かった。そこだけ、明確に顔を動かさないと見ることができない。そもそも横にモニターを並べると結構首を動かすことになって辛い、という体験談も聞いたが、僕の机はかなり奥行きがあるので、今まで免れていたのだろう。

昨日発見した、WindowsUbuntuでプログラムの出力が違う原因を探っていた。実行にそれなりに待ち時間が発生していたので合間合間に本を読みつつ、USBメモリでデータを移してdiffを取る作業を繰り返す。結局昨日予想していた原因はほとんど関係なかった。ライブラリのバージョン違いでもちょっと変わっていたが、最終的に決め手になったのはリストの順番で、とりあえずソートしたら見事に一致した。しかしなぜそれが結果に影響するのかがわからないままである。むしろ影響してはいけない箇所のはずなのに……。

本を1冊読了。「かくりよの宿飯」8巻。大旦那様と再会するまでは剣呑な空気が続くのかと思っていたが、あにはからんや、この巻もそれなりにまったりしていて、安心して読めた。ついに次巻で再会できそうだが、ストーリーが終わるのは10巻なので、まだひと悶着あるのかと戦々恐々としている。

上の段のモニターがスリープで黒くなると、結構視界に入って圧がすごいことを実感した。とはいえ、基本的にパソコンをつけっぱなしで寝る人間なため、スリープを完全に切ると部屋が明るくて困る。

シャワーを浴びて大学生協ラノベの新刊を注文し、日記を書いて布団に移動。

ハーメルンの捜索掲示板をまた漁りまくる。ちょっとでも気になった作品はスマホChromeのタブに開き、保存している。パソコンのタブはシャットダウンすると復帰する手間がかかるが、スマホだとアプリを落とそうが再起動しようがタブを保存してくれるのでかなり便利。少し前まではかなり神経質にタブを閉じていて、ほぼ常に無の状態だったので、スマホのブラウザでタブを開きまくっている人のことを理解できなかったが、今は読もうとしている作品・読んでいる作品で100個近いタブが開かれている。人は変わるものだ。

1作、最近連載が始まったばかりで毎日更新の良さそうなものを見つけたため、最新話まで追いついておいた。

https://ncode.syosetu.com/n4583he/

逆行転生悪役令嬢もので、財閥を動かす話ということで、かなり「現代社会で乙女ゲームの悪役令嬢をするのはちょっと大変」に似ている。「現代社会で~」は僕のかなりお気に入りの作品であるから、当然こちらもかなりツボに入った。1話目のあとがきによれば作者は架空史ものを書いてきた人で、なろうで人気の架空史が逆行転生知識チートものばかりであることに対するちょっとした皮肉としていろいろ設定を作ったらしいが、それはそれとして純粋に面白い。

さらに以前読んだなろうを読み返したりした後、午前11時に就寝。

09/15(水)

午後5時起床。ちょっとコードゴルフをした後学食に行き、その足で原付を買った店に行って保険の更新をしてきた。

年齢が上がっただけで保険料が1万円くらい安くなってたまげた。それでもまだ25000円くらいしている。これまで1年に100kmも乗らない原付に対してそれ以上の額の保険をかけてきたのかと思うと、かなりもったいないと感じてしまう。もちろん、たまたま自分が事故を起こさなかったからそう思えているというだけではあるが。

電車に乗ってまた駅前の電気屋に行く。5枚あるうち右上のモニターは見上げにくく、さらにサブマシンに2枚あっても使いどころが少ないことが分かったので、これまでバックグラウンドで垂れ流していた作業用BGMの動画でも表示させておこうかと思うが、そのためにはパソコンから音声を出力できる必要があった。ということで、スピーカーを買う。ついでにUSBケーブルを購入してHHKBを有線でつなぐことにした。bluetoothだとかなり不安定でよく変な挙動をするし、数分操作しないだけで電源が落ち、復帰のために数秒電源ボタンを押さなければならないのもつらい。

どちらも1000円ちょっと。ついでにオンラインゼミのための板タブレットでも買おうかと思ったが、ネットで調べていたより値が張ったので今日は見送る。会計のときにポイントカードを出したら、先週使った金額の10%にあたる1000円弱のポイントが使用できて、かなり安く済んだ。ポイントカードの威力を思い知らされた形だ。

そのあとはゲーセンで深夜まで遊んでいた。最初の数クレは駅前のゲーセンで手元を撮影していた。

スマホアーム付きの台に待ちができたので移動して新曲のAJ埋めをした。前回ゲーセンに行ったときから狙っていたParad'oxのAJを出せて満足。

最後のほうはHAELEQUINを詰めていたが、どうにも敷地帯ができない。1度など敷地帯以外ほぼAJだったのに、緊張で運指が吹っ飛んでしまった。ノーツが2000ノーツしかなく、赤を100個以上出すので、鳥許容はアタック7個と最近の13+に比べたらかなり少なく、適当にやっていては出ない。でもまあ、今日プレイした感じでは、敷地帯の運指をちゃんと組むことがSSSを出すことの(必要かつ)十分な条件だろう。

帰りにそばかラーメンでも食べようと思ったが、どこの店もやっていなかった。ドンキでパンを買って帰宅。

パソコンにスピーカーを接続したら、マウス操作のたびにゴソゴソと音がする。

ネットで調べた感じでは、別の回路のノイズを拾ってしまっているらしい?音量を0にしても相変わらず出ているので、これは別のものを買わないとダメかも……と思っていたが、ふと給電用のUSBだけ違うパソコンに差したら解決した。謎だが、別のスピーカーを買わずに済んでよかった。このスピーカーはモニタースタンドにぴったりのサイズなのも面白い。

しばらくコードゴルフをしていたが、最近あまりに何もやっていないことが気になったので、とりあえずECR埋めを進めた。月曜日のECR18-Fはあんまりピンと来ないので放置して、今日はECR19。

Dashboard - Educational Codeforces Round 19 - Codeforces

Aはよい。Bはdpしたが、貪欲でもできないことはなさそうだった。Cは貪欲。Dはsetを持ってマージテクしつつ木dpだが、全然関係ない場所にある同じ値を検出してもよいことを失念して1WA。Eはk\sqrt n以上か未満かで処理を分け、前者は毎回シミュレート、後者は前計算。Fは2次元dpを考えて遷移をスライド最小値で高速化。

さらにECR20を開き、A-Eを埋めた。

Dashboard - Educational Codeforces Round 20 - Codeforces

Aは面倒そうな場合分けを考えていたが、書くうちに本当にただの貪欲でよいことに気づいてびっくりした。Bはよい。Cはgcdを全探索して、構築は基本1,2,\dots,k全体を定数倍、最後の要素を増やして調節。Dは二分探索。空白とハイフンの扱いは結局のところ一緒なのに問題設定のために別の扱いをされていて非本質的。Eはdp+復元。

Fに詰まったので切り上げて布団に入り、今日もまたハーメルンの捜索掲示板を徘徊する。自分のツボに入った作品の名前で捜索掲示板を全文検索すると、似たような作品を沢山見つけられて生活が破壊されることに気づき、今日はもっぱらそんな感じでやっていた。しかし見つけた作品のタブを大量に開いた後は、前から読み返していたハーメルンの続きを読んでいて、新しい作品には手を出さなかった。

午前11時くらいに寝落ち。

09/16(木)

午後3時から30分おきの目覚ましで意識を取り戻しつつ、最終的に午後4時半に布団を脱出した。

この構文が人気なことは知っていた。一般に広く知れ渡っていると思っていたが、実のところ特別音ゲーマーの間で流行っているらしいと誰かから聞いたのだった。音ゲーの運営がオマージュしたことで、そのことを強く感じた。ネタにするには結構危険な構文じゃないか?と思っていたが、さすがに運営としての自覚はあるらしく、言葉遣いはかなり配慮されていてあまり原型を保っていない。それでも肝は抑えてあって、個人的には評価は高い。

午後5時から1on1。火曜日の夜(水曜日の朝型?)行っていた検証の話をして、これ以上の追加調査はとりあえず必要ないという結論に至った。それ以外に進捗はないため、あとは少しばかり雑談をして終了。会社としてインターン生、より一般にエンジニアが無理なく働ける体制を整えることを重要視しているらしく、僕が生活リズムを崩壊させていても、それでは1on1の時間をずらしましょう……として下さる。以前までの自分であれば、これぞ求めていた働き方だの、やはり生活リズムを整えることは非本質的だのと考えていただろうし、実際そのような思いは今もあるが、自分にとって一概に良いとは言えないことに気づいた。結局生活リズムを崩して進捗を産めなかったとき、その代償を支払うのは自分なのだ。そして、僕は1人では生活リズムを正すことができない……。

しばらくYouTubeを見たりハーメルンを読んだりした後、学食に行って夕食を摂った。帰ってきてからTCB40に参加した。いつものように、日曜日までのコンテストなのでここに問題の感想を書いておく。先に言っておけば、今回は理論値を達成できたものの、最終問題を詰めるのにかなり時間を食ってしまったため、そこの差で優勝はできていなそう。

https://techful-programming.com/user/event/2242

5問目は何でもできそうでちょっとびっくりしたが、結局各要素の出現回数をカウントした。6問目と7問目はほぼ一緒の問題で、両方imos法をやるだけで謎。8問目はN素因数分解する必要があることに提出直前で気づいて助かったが、その分書き直しに時間を取られた。9問目は明らかだが座圧が面倒だった。10問目はまずディーラーの戦略を整理して勝率を式に表し、適当な範囲で和を取る。範囲を定めるのと式中のmaxの値でさらに場合分けするのをこれでもかというくらい念入りに行っていたら20分もかかってしまったが、その甲斐あって1発でACした。確か時間で点数を引かれるのは想定時間の3割以降だったから、この問題は大体24分、結構危なかったらしい。

日付が変わるまで布団に転がってハーメルンを読んでいたが、今日も何もやっていないため、またECRの続きをすることにした。パソコンの前に戻ってきて、ふと思い立って画面キャプチャのテストをしてみたところ、これまで真ん中のメイン画面をキャプチャできていたのが、いつの間にか左端の画面をキャプチャするようになってしまっていた。調べたところ、regeditでモニタの設定をいったん削除し、改めて番号順にモニターを1枚ずつ増やしながら接続→再起動を繰り返すと正しく設定できるらしい。面倒だったが、何とか真ん中の画面をキャプチャするように戻って安心。

ところで、regeditといえば「人類が増えすぎたので減らしてほしいと頼まれました」というなろうを思い出す。4話目のあとがきにこれが元ネタだったと書いてあった。このなろうは100話くらい読んで放置している。

https://ncode.syosetu.com/n0859fa/

ECRを進める。昨日の続き、ECR20-FGから。

Dashboard - Educational Codeforces Round 20 - Codeforces

Fは昨日、square-freeにして包除したい気持ちになっていた。今日改めて考えなおしてみると、包除に関係する各値は個数さえわかればよく、対応する値にいちいち加算していてもそれほど多くはならない。Gはパッと見厳ついが、区間の区切りだけ取り出して列の圧縮を行うと普通の区間set区間minの遅延セグメント木になる。すぐ気づけてニコニコ。前計算に使用したセグメント木にクエリを投げていてサンプルが合わず、実はsegtree beatsをする必要があったかと焦ったが、そんなことはない。

ECR21。Fは諦めた。GはAho-Corasickのfailure関数を使うはずだが、ライブラリを持っていないので、この機会に作ろうかどうしようか迷ってコーディングしていない。

Dashboard - Educational Codeforces Round 21 - Codeforces

ABはよい。Cは貪欲。Dは左右に分けたとき要素を1つだけ移せると言い換えられるので、分ける仕切りをずらしつつ条件を満たせる要素が存在するかsetでチェックした。Eは重さ3の荷物を何個とるか全探索し、重さ2の荷物の個数で三分探索。

しばらくハーメルンを読んでいた。最近は、今年初めに読了した以下の作品を読み返していた。特に、それまで幻想郷では正体を隠していた世界最強の主人公がその正体を顕わにする緋想天編のラストシーンがお気に入りで、その周辺は定期的に読むのだが、ここ最近は幻想入りのあたりから一連の流れをまとめて読み返していた。やはり面白い。最後までたどり着いて満足。

syosetu.org

朝方、ほかの人の先週の日記を読んだ後、溜めていた自分の日記を書いた。それが終わってからまたハーメルンの捜索掲示板をひっくり返す。今日は「現代社会で乙女ゲームの悪役令嬢をするのはちょっと大変」で検索していた。えらい似たタイトルが引っかかるなあと思っていたら、この作品の2次創作だったらしい。短編だったのでサクッと読んだ。シン・ゴジラを見ていないのでよくわからないが、文章などそれなりに原作と似ている感じはして、いいんじゃないだろうか。

syosetu.org

ゴミを出して布団に入り、紙の本を少し読み進めて就寝。午前10時半だった。

09/17(金)

午後8時半起床。今日は外せない用事が何もない日だったので、何も気にせず目いっぱい寝た。

大学院に合格したはいいものの、入学意思確認書を提出できていない。今週はもう終わってしまった。期限は09/22(水)である。火曜日あたり徹夜して直接教務課に出しに行きたい。

午後9時20分からyukicoder 314に出た。

yukicoder contest 314 - yukicoder

Aから難しい。XY平面にプロットすると、ひし形内部の格子点を数える問題になる。なんというかギザギザな分布をしていて面倒。45度回してひし形を長方形にしたらいいのかな……と思ってふと、最初から45度回転させておけばよかったことに気づいた。そちらでも求める格子点がギザギザに分布していることに違いはないが、縦横がちゃんと座標と合っているので、真面目にやれば場合分けできる。Bは何も考えずに積と以前の和を持ってdpした。これは2019年JAG夏合宿day1Gで似たようなことをやったのを覚えていた。が、聞くところによると大体の項が正負で打ち消しあって消えてしまうらしい。いやそんな考察いるか?という気分ではあるが、面白さはわかる。

https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2973

Cは非常に面白かった。コインを加えた時の確率漸化式を求めてみる。Aliceが勝つ確率をpとしたとき、pではなくp-(1-p)=2p-1から遷移してみると、見事に因数分解できて、最終的な形が各コイン独立な値の積になった。ほぼ同じことだが、p-\frac 1 2から遷移する方法もあるらしい。こちらは答えへのたどり着き方が少し違う。Dは適当に全探索。

Eはかっこ列を2次元平面の経路に帰着させるやつを行う。二次元平面を斜めにおいて、左端がスタート、右端がゴールとしたとき、ゴールは右端で上からいくらかの区間になっている。足さなければならないかっこの数は、スタートからゴールまでの経路で一番上下にぶれた幅で決まるので、ある場所より上・下にいかないような経路数を求めたくなる。これは2次元平面を斜めに切って反転させるテクニックで計算できる。ゴールとなる区間が下にはみ出ると面倒そうなので、最初は2M\le Nの場合だけで解いていた。このとき何を思ったかM\leftarrow N-Mとしても答えは変わらないと思い込んでしまい、サンプルが合わずしばらく苦しんでいた。気づいて絶望しそうになったが、2M\le Nの場合の答えを何種類か求めることで「全体」引く「M\leftarrow N-Mとした場合の答え」が計算できたのでOK。

本を読みつつ時間をつぶし、日付が変わったぐらいからSRM813。oo-で33位、レートは2480→2443(-37)。Medが遅すぎた。

TopCoder Statistics - Match Overview

Easyは自明。Medは最初にdp[Sの何番目][区間が始まっていない会社の個数][区間が終わっていない会社の個数]を書いた。状態O(SC^2)で遷移は「区間を始める会社を選ぶ」→「区間を終わらせる会社を選ぶ」でO(C^2)。これでサンプルが合うことを確認した後、どうやって高速化しようかずっと悩んでいた。実は、今遷移を2重ループで書いているが、1重ループを2回書いても全く同じことができるので、もう4乗になっている。気づいたときは自分の頭の悪さに絶望した。しかしSRM Medの600点の難易度感がよくわからない。今回はたまたま解法ガチャに正解しただけか?

残り20分でHardを読む。たぶん大きいほうから全探索で行けるだろうなという気になり、実際パターンが1桁の場合を検証してみたが、そこで2桁の場合の実装に絶望して諦めた。

ことらんさんの「下水を再利用した街を作る!」シリーズ4本目の動画が投稿されていた。1年くらい空いたのだろうか?今回も非常に面白かった。SRMの残り時間はコメあり・なしで2周していた。

www.nicovideo.jp

チャレンジをコンテストの1部だと認識していないため、コーディングフェーズとチャレンジフェーズの間でも平気でTwitterにコンテストの感想を流してしまう。さすがに直接的なことは書かないようにしているが……。今回のEMは落ちようがないだろうと思っていたが、Medが結構落ちて、システス前から9位くらい上がった。それでも元の順位が低すぎてレートには大ダメージ。Medで包除原理をしていた人が多いと聞いたが、そちらの解法はよくわかっていない。

深夜から昼前までかけて本を読んでいた。「かくりよの宿飯」9、10、11巻。10巻がシリーズ完結で、11巻は短編集だった。非常に面白かった。

まず9巻から。同作者の別作品と多少リンクしているという話は何度もあとがきで目にしていたが、この巻を読んでいる最中にやっと、このシリーズの主人公(津場木 葵)と別シリーズのキャラクター(津場木 茜)の苗字が同じであることに気づいた。よく描写を見れば、以前の回想シーンに津場木 茜らしきキャラが登場していた。髪の毛が橙色という超特徴的な容姿をしているのに、なぜピンとこなかったのだろうか……。

またこの巻で、大旦那様の好物が明らかになる。大旦那様が弁当を食べるときに最初に口にするものだと言われて、そういう伏線が……!と思いつつ9巻の弁当シーンを一通りさらってみると、確かにそうなっている。そういえば1巻冒頭にも弁当シーンがあったな、と思ってそちらも確認したが、残念ながらそのときはれんこんのきんぴらで、9巻で明かされた内容とは矛盾していた。まあシリーズ始めから続くような伏線を用意するのは難しいか。

次に10巻。5巻で登場した敵キャラは物語上のラスボスだったようで、この巻まで嫌らしいことを何度もやっていたが、ついに倒された。伏線という明確な形ではないが、これまでのシリーズで培われた各キャラの特性が存分に生かされてクライマックスを盛り上げており、非常に良かった。大旦那様が天神屋に帰るシーンはなんとも感慨深く、涙が出てきた。そんなシーンでも口調を崩さないキャラのせいおかげで、シリアスな場面にも一つまみの笑いがあるのは、シリーズを通しての特徴かもしれない。

勢いで11巻も読み切った。完結して数年後の話。これまで登場したキャラが総出演で、元気な姿を見ることができてうれしい。いろいろ関係性は変わっていたが、みんなあるべき場所に落ち着いたという感じがした。ただ欲を言えば、もうちょっと現世での話も読みたかったか。主人公と大旦那様が現世で一緒に買い物をしているとき、大学の同級生と遭遇して、大旦那様がキャーキャー言われる……というのは非常に僕好みの1シーンだろうが、回想という形でサッと流されてしまった。天神屋の社員旅行で現世に行くという話が、何度も語られているにも関わらず結局この巻に描かれなかったので、また別の外伝が出るのではないだろうかと楽しみにしている。

さて、2週間とちょっとかけて「かくりよの宿飯」シリーズを読み切った。記憶が新しいうちに同作者の「浅草鬼嫁日記」のほうを読み返して、リンクしている箇所を探してみたいと思う。今は本が実家にあるので、そのうち帰省したらやってみよう。

ECR22のA-Dを埋めた。

Dashboard - Educational Codeforces Round 22 - Codeforces

ABはよい。Cは2頂点からそれぞれ最短距離を求めて、相手よりも自分からのほうが近いような頂点にはたどり着けるので、その中で相手から最も遠い頂点を探せばよい。似たようなことはARC078-Dでやった。Dは2つの部分列を作るのに、現在見ている要素が先頭になっていないほうの部分列の先頭を持っておくdp。問題タグにflowと書いてあってびっくりした。

D - Fennec VS. Snuke

布団に入る。くいなちゃんがミステリー小説を書いたらしいので、読んでみた。一口サイズでいい感じ。様々な可能性が丁寧に潰され、確かに不可能犯罪のように思えたが、解決編で明かされたトリックは割とあっさりしていてびっくりした。多分一番のミスリードは、作中の探偵が誤った結論に達していた部分で、問題編最後の描写も含め素人探偵に対する批判的精神があって面白かった。

くいなちゃんミステリー - くいなちゃん小説

さらに少しハーメルンを読み、午前11時に就寝。

09/18(土)

午後7時起床。

起きてtwitterを見たら、今日の昼頃行われたJOI一次予選の問題が2時間前に公開されていてびっくりした。慌てて解いたが、自明な最短はもうすでに取られていた。AとBはdc、CとDはRaku。Bはテストケースハックで、Dは良さげな演算子を見つけてそれぞれ縮めることができた。

JOI 2021/2022 一次予選 (第1回) 過去問 - AtCoder

午後9時からABC219。今日は7完。序盤にペナを重ねてつらい気持ちになったが、FGあたりをそこそこ速く解けていたらしく、順位表の1ページ目にいた。ただ賞金は逃したようだ。

Sciseed Programming Contest 2021(AtCoder Beginner Contest 219) - AtCoder

Aは面倒。とりあえずAWKで出したらFAだった。直後自明な更新ポイントがあったので1B縮めておいたが、現在の最短は言語から違う。BはPerlで解いた。Cはbashで出したらWA。よくわからない仕様を踏んだかと思ってC++で書き直したが、実は文字を置換する順番が違っていた。

Dは適当にdpを書いたらWA。問題文を読み直したときに、たこ焼きとたい焼きが一瞬同じ単語に見えてびっくりした。しばらく考えて、XYを大幅にオーバーするケースも考慮しなければならないことに気づいた。どうやって書けばいいのかすぐにわからなかったが、しばらくしてオーバーした部分は無視してよいことに気づいた。

Eは面倒。堀をdfsやらで探索するクソ面倒な問題かと思ったが、視点を変えて堀の内側に入れるマスの集合を全探索すればよいことに気づいた。意気揚々と実装して、堀の内側のマスの連結性もチェックし、サンプル1を試したところ、1720が出てしまった。validと判定されたマスの集合を全部出力して適当ににらめっこし、内側に穴が開いたケースが怪しいことに気づいた。問題文からはそういうケースがvalidかどうかよくわからなかった(同じ勘違いで1720が出た人が大量にいたらしい)が、とりあえず省いてみる。省くのも結構難しく、いろいろ考えた結果、周囲1マスを増やして堀の外側も連結になっているか調べることにした。これで再度サンプル1を試すとちゃんと正しい答えが出たので一安心。

Fも面倒。1回の文字列で移動する差分と通過するマスを求めたとき、掃除されるマスの集合は、1回の文字列で通過するマスたちに差分を適当に足した形のマスになる。その重なり具合を調べればいいので、差分をうまく足し引きして通過するマスの座標を正規化し、それの一致を見ることで重なりうるマスをまとめ、それぞれについて差分を何回足した場所のマスが掃除されるかを、区間の和を求める感じで計算すればよい。

Gは最近ほとんど同じ問題を見た覚えがあって、怪しみながら次数の平方分割を書いたら何の問題もなく通った。僕はPASTの過去問(PAST5-O)を思い浮かべていたが、それより典型90問の83問目がよっぽど似ていたらしい。確認したらほぼ同じだった。Hは適当に枝刈りしたら案の定TLEして、なんとなく凸包っぽさを感じたあたりで、残り時間が10分もないこともあって諦めてしまった。

083 - Colorful Graph(★6)

コードゴルフ。Aはdc。BはVimで置換するコードを作って実行するのが短いらしく、Rakuで配列のインデックスを使うコードを書いたがVimより1B長かった。Cはコンテスト中に置換の順番の間違いに気づきbashで提出、その後Vimで出したものが最短。Eは僕のC++が現在の最短になっている。

DはOctaveのglpkで解ける。(ところで、cygwinからOctaveを起動するとやたらめったらオーバーヘッドがかかって非常に重いので、Ubuntuにインストールしてこれからはそちらでコーディングすることにした。)さて、glpkで適当に書いて提出したところ、1ケースREしてしまった。ケースが公開されていないのでなぜ落ちているのかわからない。とりあえず入力フォーマットは正しい。しばらくテストケースの特定作業をした結果、N=2で答えが2であるようなケースでREしていることが分かった。そこでいろいろ入力を変えて試していたところ、X=Y=300A_i=B_i=151\;(i=1,2)のケースでglpkがエラーを出すことに気づいた。おそらくglpkのバグだろう。

どうしようもないので、最初はN=2のケースがこれ1つしかないことを利用して、場合分けして直接2を出力するようなコードを書いて通した。その後、入力を増やすことを思いつく。A_{N+1}=B_{N+1}=0という弁当を増やしても答えには影響しない。残念ながらこの通りの弁当だとREは解消されないが、A_{N+1}=-1にしたら通った。

午後11時半からCF #743 div.1。ジャッジが詰まりまくってunratedになった。ABが難しくてWAを出していたので助かった。

Dashboard - Codeforces Round #743 (Div. 1) - Codeforces

AはDAGチェックして最長パスを求める問題。ループ検出に失敗して1WA。最長距離が更新されない頂点があったときにループがあると判定していたが、これは誤りで、ループがあってもその外から最長距離を更新される可能性はある。

Bは難しい。基本的には左から貪欲に消していきたいが、左端が1だった場合が困りもの。この場合はそこから右にずっと見て行き、左端から1が続く連結成分のサイズを偶数にできたら(さらにそれが列全体でなければ)OK。最初から連結成分のサイズが偶数の場合はそれでよいが、そうでない場合は途中適宜操作して0を1にしつつ、うまく別の1の場所まで伸ばして、連結成分を1減らすような操作をする必要がある。コンテスト中は、左端がダメでも右端からできるならOKだということで、左右反転して2回チェックしていたが、実は左からだけでよい。左から上記の操作をして列全体になってしまったなら、右から操作してもそうなる。

Bを解いている最中にunratedが決まり、それからはABCに戻ったりして遊んでいたが、情けない結果を残すのも恥ずかしかったので改めて解いていた。Bを通して一度は満足したものの、しばらくしてCも解けたので実装。残り20分もないなかギリギリで書ききって投げたら9ケース目でREした。配列外参照を見つけて修正し、システス後に投げたら通った。Cは基本的には区間dpで、ただし本質的な場所だけ計算する。本質的な場所とは区間の両端が同じ色で塗られているようなもので、そのような区間は謎の制約から高々20N個しかない。区間の長さでソートして、以前の結果を使いつつ毎回O(N)のdpをする。

ABC219-Hを解説を見て通した。難しいデータ構造やアルゴリズムを使うのかと思ったら全然そんなことはなく、ただただ頭のいい言いかえを繰り返してdpに帰着しており、びっくり。僕も区間dpは少し考えたが、距離とスコアを同時に持てなくて棄却したのだった。その距離を、いろいろな言いかえ・計算の分解を経てO(N)種類の値に収めるのが本質。

朝方ハーメルンを1作読んだ。「創造神が行く幻想の世界」。設定は良さそうだったが文章がカスであまり身が入らなかった。序盤など、もともと台本形式だったものに無理やり地の文を足したらしく、リメイクと称してはいるがただただ読みにくいだけ。オリキャラたちもそれほど好きになれない。ただ、今がちょうど幻想入りしたあたりなので、これからはちょっと面白く感じられる可能性がある。

syosetu.org

布団に入ってしばらくハーメルンを読み、午前11時半に就寝。

09/19(日)

午後4時と4時半の目覚ましでは、意識を取り戻しはしたものの、布団から這い上がれなかった。午後5時ギリギリになってようやくパソコンの前に座った。今日もOpenCup。よくわからないのでリンクは貼らないことにした。

今日はチームで7完。相変わらずチームメイトが強い。明確に得意分野を持っている人という印象で、こんなの無理やろと思っていた問題を通していくのを見てすごいなあと言っている。解法を追っかけているわけではないため自分の身になっていないのがもったいない。僕も2問書いたので先週よりはチームに貢献したと思うが、両方ギャグみたいなものだった。

具体的にはAとHを書いた。Aは真っ先に読んでちょっと考えたが、OpenCupだし激ムズ問題しか出ないだろうと恐れをなして逃げ出した。順位表でかなり通されているのを見て再度考え直し、ギャグの構築であることに気づいた。Hはチームメイトとしばらく考えていたが、まっとうに構築しようとすると頭が壊れたので、適当に生成して埋め込むのをやってみた。案外早く全ケースに対する構築が見つかって、むしろファイル出力だったり、そこから1つのソースコードにまとめなおすほうで少し手間取っていた。僕はサイクルに対角線を張るのを試していたが、maspyさん曰く、ちょっと確率調整したランダムグラフでもすぐ見つかったらしい。

残り時間でGを考えていた。僕は、答えをパターン分けして、それぞれいくらか重複しつつ数え上げたあと、うまく線形和を取ることで答えの値だけ得られないかということを試行錯誤していた。結局それはうまくいかないままコンテストが終了してしまったが、終わる直前にチームメイトが、値を2種類だけ計算することでうまく相殺されるような式を見つけていた。コンテスト後に投げたら通ったらしい。

さて、OpenCupが終わったら直後にARC126だったのだが、その前に、OpenCup中に両親が仙台に来てくれたことに触れておきたい。

結局この夏は富山に帰省しないことにして、代わりに両親が車で仙台まで来てくれた。時間が遅かったので夕食を食べに行くようなことはなかったが、母がラーメンを作ってくれた。自分の部屋のキッチンからまともな料理が出てくることに新鮮な驚きがある。そして、持ってきてくれたお菓子や総菜を部屋に収納し、代わりに既読本だったり大きな段ボールだったりを持って帰ってくれた。滞在時間はかなり短かったが、また近く免許更新のため富山に帰るので、それまでしばしのお別れである。

午後10時からARC126に出た。5完9位。

AtCoder Regular Contest 126 - AtCoder

Cまで通した時点で1位と、序盤はかなりいいペースだった。そういえば先週もOpenCup後にCGR16に出て大成功したのだったか。5時間コンテストの直後はヘナヘナになっていて、別のコンテストに出てもまともに問題を解けないだろうと考えていたが、実はそんなことはないようだ。僕が考えるに、おそらくOpenCupの問題に手も足も出なくて精根尽き果てるほどの考察をしておらず、結果長いコンテストの間にいい感じに眠気が取れ、リラックスし、それでいて頭は競プロモードに入っているのが良い影響を及ぼしているのだろう。あるいはたまたまCGRとARCで得意セットが続いているだけか。

Aは丁寧にやる。考察の流れはこんな感じ:まず長さ3だけ奇数なので2本まとめ、次にすべての棒の長さを2で割る。長さ3の棒とペアにするのは長さ2を1本か長さ1を2本のどちらかで、長さ1を残したほうが後々動きやすくなるため、長さ2と優先的にマッチングする。これで棒が2種類以下になるので、あとは答えまでストレートにたどり着ける。

Bはa_iでソートして実家dpしたい気分になる。a_i=a_jなるijを同時に使わないように、タイブレークb_iの降順にしておけばOK。Cは、答えが\max Aを超えるようならばただの割り算で求まる。そうでない場合は、例えばgが答えとしてありうることはK\ge\sum\left(\left\lceil\frac{A_i}g\right\rceil g-A_i\right)が必要十分だが、この\left\lceil\frac{A_i}g\right\rceil gとしてありうる値が\frac{\max A}{g}種類しかなく、1つ1つ見ながら累積和を使うことで必要な操作回数が求まってチェックがO\left(\frac{\max A}{g}\right)でできるため、1\le g\le\max Aを全探索できる。

Dはちょっとハマった。順列をどれだけ作ったかをキーに持つbitDPをする。見ている要素を順列の外に避けるか、あるいは順列の1部として組み込むか。このうち外に避ける操作の際、作っている順列の左右どちらに避けるかでコストが違うので、両方計算して小さいほうを取らなければならない。ここの処理をよく考えておらず、最初にACしたコードでは左右からそれぞれbitDPして(左から作った順列は左にしか避けない遷移になっている)、最後にマージしていた。マージにO(K)かけたので全体でO(NK2^K)となり、さらに一番内側のループで毎回__builtin_popcountを呼び出していたので、1000msくらいかかっていた。

Eはエスパー。サンプル1の2回目のクエリを考えてみる。数列の全体から5を引いて(0,0,1)であるとしてもよい。これに対し、隣接する2項(a,b)(\frac{a+b}2,\frac{a+b}2)にする、という操作だけ何度か繰り返してみた。すると(\frac 1 4,\frac 1 4,\frac 1 2)が得られ、点数は\frac 3 4点となる。また全体から\frac 1 4を引くと、元の数列を\frac 1 4倍した形になっていることに気づく。つまり、この数列に対するf(n)の極限は\sum \frac 3 4\times\left(\frac 1 4\right)^i=\frac 3 4\times\frac 1{1-\frac 1 4}=1と計算できて、サンプルの値と一致する。

3回目のクエリも考えてみる。今度の数列は(0,1,2)。初手で(0,2)を選んで操作すると1点で終わってしまうことから、どうやら一般にソートしたときに隣接する2項を選ぶのが最適なように感じられる。とりあえず(0,1)で操作すると(\frac 1 2,\frac 1 2,2)\rightarrow(0,0,\frac 3 2)で点数は\frac 1 2点。ここで、先ほど(0,0,1)から1点が得られたので、両方\frac 3 2倍することで(0,0,\frac 3 2)からは\frac 3 2点が得られることがわかる。実際\frac 1 2+\frac 3 2=2となって、こちらもサンプルの値と一致する。

ここでエスパーをする。与えられた数列をソートして、隣接する2項をならす操作だけ考えればいいのではないだろうか?しかもそれは左から順に行われる。いかにもよさそうな見た目をしているので、これで考察を進めることにした。まず、点数を計算するために、(0,0,\dots,0,1)をならすとどれだけ加点されるかを計算することにした。(0,1)=\frac 1 2(0,0,1)=1(0,0,0,1)=\frac 3 2。どうやら数列長に対して線形らしい(ここもエスパーしたが、右端の(0,1)(\frac 1 2,\frac 1 2)と操作することで帰納的に示せるようだ)。

さて、先頭i\;(2\le i\le N)項をならすことを考える。先頭i-1項はならされているので、その値は平均、\frac{\sum_{j=1}^{i-1}A_j}{i-1}。これを先頭i項から引くことを考えると、先ほど点数を計算した数列の定数倍になるので、得点もその定数倍、具体的には平均を引いた後のA_i\frac{i-1}2倍した値になる。まとめると、ソート済み数列に対する答えは\sum_{i=2}^N\frac{i-1}2\times\left(A_i-\frac{\sum_{j=1}^{i-1}A_j}{i-1}\right)となるようだ。

適当に\sumを分解することで、\frac{-N-1}2\sum A_i+\sum A_i\times iを得る。これは1点変更が発生しても差分を考えれば更新できる。ソート済み列に対する挿入・削除を実現すればよくて、挿入は、自分に振られるインデックスを求めて掛けた後、それより後ろにある要素はインデックスが1増えるので、値の総和だけさらに増やす。BITで要素の分布と分布に対する値の和を持つことで計算でき、削除も同様。今回は値が大きいのでクエリ先読み+座圧が必要。実装して、サンプル2はN=2なのであまりあてにならないがとにかく答えが一致することを確かめ、提出。

WAを食らって絶望してしまったが、オーバーフローだった。答えのmodを取らなければならないことに終盤気づいて、出力の部分だけ書き換えたのだが、値を保持する変数もmodintにしておく必要があった。値とインデックスの積の和は最大で\frac{N^2}2\times 10^9\approx 4.5\times 10^{19}くらいになる。

Fに1時間近く残したが、そこから何一つ進まなかった。初手何をすればいいのかすらわからない。メタ的に考えて、(a,b,c)は3次元空間の点だと思えるから、整数じゃなくて実数の領域として極限値を求めるのかなとも思っていたが、それで何か得られたわけでもなかった。

コンテストが終わったあたりでTCB40の順位表が更新され、最終順位が出た。最終問題がかなりてこずる問題だったらしく、単独理論値を出して優勝した。時間的にも10完勢の中で一番速い。最高!TLを見た感じでは8問目のコーナーケース(L=0N=1か?)も凶悪だったようだ。

コードゴルフ。Aは朝方dcで通した。思いのほか短くなった。アルゴリズムを吟味するために、短めのコードをいろいろと読んで、結局僕が使用したのはこの提出と同じもの。

atcoder.jp

BはABC038-Dと全く同じコードで通る。そこからさらに縮んだが、現在の最短を思いついたのが少し遅く、ARCのほうでは最短を取られてしまった。ABCのほうは僕が出したコードが最短になっている。Cは手を付けていなくて、DはCrystal。

D - プレゼント

最近いろんな人がCodechefに出るようになっている。最初出会ったときに謎インドコンだと思って敬遠したっきりなのだが、やっぱり自分が出ていないコンテストがあるとちょっと焦燥感がある。今からでも始めるべきかもしれない。

週記(2021/09/06-2021/09/12)

09/06(月)

先週の週記を投稿した後は、しばらく人の日記を読んだりKaggleでよく使われているモデルについて調べたりしたあと、布団に移動してしばらく本を読み、午前9時半に寝た。

しかし、ここで先週の週記に書けなかった日本橋ハーフマラソン増刊号の初動についても触れておきたい。この問題では過去の動きが将来にかなり大きな影響を与えるようなので、最後まで操作列を作ってから途中を弄るのは難しい、というより不可能だろう。ということでビームサーチを書きたいが、どういう風に書くかよくわかっていないので、とりあえず幅1のビームサーチに絞って書いてみることにした。

盤面の評価値は、これまで稼いだ金額にプラスして、まだ収穫しておらず枯れてもいない各マスの価値を収穫機からそのマスまでのマンハッタン距離で割ったものの和。これで6132813点。その後すぐ、必ず収穫機が連結であるようにして、将来の各マスの価値を生えるまでの時間で割ったものに置きかえ、さらに現在生えている価値に少し重みづけしたら、120452453点になった。連結性が効いたのだろう、実際その後重みづけを変えて、将来の各マスの価値により大きな係数を掛けると、133149923点になった。これまで稼いだ金額との比も重要のようだ。この点数は当時1位だった。

このあたりでビジュアライザに掛けてみると、将来的なマスの価値を重視するあまり序盤の動きがかなり遅いと感じた。そのため、収穫機が1台の間は現在の価値だけで遷移してみたが、逆に点数は下がってしまった。序盤のマスの価値は終盤に比べて十分小さいため、無視してよいのかもしれない。ここまで貪欲法で実装しているが、実行時間が1800msとちょっと心配なので、適当に高速化。200msくらい削って同じく133149923点を出すコードを提出し、この日は切り上げた。

午後3時半起床。しばらくコードゴルフをして、午後4時半からインターン先の週1のミーティングに参加した。先週の成果を報告する場で、僕が今週発表することは想定されていなかったのか特に資料など用意するようには言われていなかったが、せっかくなので1日稼働してやったことを口頭で述べた。ミーティング自体は問題なく終了。その後勉強会の時間があった。今日はパズル系の発表で、ミーティングに参加している人々と共に頭を働かせた。かなり興味深かった。インターン生でも発表してよいらしいので、毎週の様子を見つつ内容を考えておきたい。

インターン先から僕のところにパソコンが送られてくるかも、という話になったが、モニターとキーボード・マウスはこちらで用意する必要がありそう。自分のパソコンからモニターを引っこ抜くのは寂しいので新しいものを買ってもいいかもしれないが、そうすると今使っている机に並べることはできないので、ディスプレイアームが必要になる。僕はパソコンデスクとしてダイニングテーブルを使っていて、これは幅も奥行きもあってかなり広々使えるのだが、ディスプレイアームの設置に対応しているのかだけが心配。一度駅前のヨドバシカメラにでも行って現物を確認する必要があるだろう。

余った時間で、Kaggleに興味がある面々が集まってチームを組もうという話になった。チームを組むということ自体に非常に興味があって、ぜひやってみたかったのだが、残念ながらコンペのチーム人数制限が3人だったので組めなかった。以前は5人だったらしい。

ミーティングが終わってからはすぐ業務に入らず、しばらく本を読んでいた。「かくりよの宿飯」5巻を読了。3巻ラストの衝撃的なシーンから続く一連の流れがこの巻で終わった。単純なので、悪役っぽい感じで登場したキャラがいたら最初は悪感情を抱いてしまうが、その後しばらくかけてそのキャラの性格や信念などに触れると、すぐ好印象で上書きされる。でも敵だったキャラが味方に付くという展開は非常にありがちなので、その点ではよいことなのかもしれない。また新たな敵キャラが登場したが、今のところはとりあえずやり込めることができており、1巻で提示されたストーリー上の謎も1歩前に進み、総じて非常に満足のいく終わり方だった。

午後8時半くらいから業務を開始して、午前1時半くらいまでずっとコーディングしていた。とりあえずコード読みの一環としてリファクタリングをしており、自分が思うきれいなコードを書こうと邁進していたが、今書いているコードは保守性が求められるものではないため、実は必要ではなかったのかもしれないという思いがぬぐえない。可読性については元からあまり変化がない、というのも、自分が思うきれいさとは、例えば型ヒントをつけてmypyでエラーが出ないことだったり、関数を切り分けたり統合したりすることであって、コメントをつけるという作業はほとんど行わなかったからである。残り1ファイルになって、少し手を入れたくらいで今日は切り上げた。

エクセルファイルをPythonから読み込むことが多いが、この作業は結構重い。僕が読んでいるコードを以前に書いた人も、その点は重々承知しており、エクセルファイルを読み込む関数をいくつか用意して用途によって使い分けていたが、なおかなりの処理時間を使っていた。ある特定のシートしか必要ではない状況にあっても全体を読んでしまっているということに着目し、特定のシートだけを読み出すような関数を用意してみたところ、かなり処理速度がアップした。手元で50分以上かかっていた実行が10分程度で完了するようになり、非常に楽しかった。

Kaggleを少し進める。ほんの少しだけ調べた結果、モデルはLightGBMがよく使われているとか、特徴量を考える作業が多いとかを聞いて、試しに適当にそれっぽい値を増やして学習させたら、スコアが結構上がった。集団を追い抜いたようで、順位も400位くらい上がったのではないか。それでもコンペの参加人数が多いためまだ順位表の下であることに違いはないが、結構元気が出てきた。特徴量というのは本当に必要なものを少しだけ用意するのがよいと勝手に思っていたが、実はそういう重要度を考えるのはモデル側がやってくれるので、こちらは関係ありそうな値を手当たり次第に放り込んで観察するのが基本的なやり方らしい。

布団に移動してしばらく本を読み、午前6時就寝。

09/07(火)

午前11時起床。かなりつらかったが、正午からメンターさんとの1on1をお願いしているため、無理やり起きる。完全に自分が悪い。信じられないくらい頭がかゆかったので慌ててシャワーを浴びたが、よく考えると昨日シャワーを浴びていなかった気もする。

正午まではマラソンの続きをしていた。ふと、昨日の評価について連結成分の大きさを考えていないことに気づいた。将来的なスコアに連結成分の大きさを掛け合わせ、重みづけを少しいじってみたところ、168165265点へと大幅に増加。何とか順位表の1ページ目に返り咲いた。

今日の1on1では、とりあえず今やっていることが終わりそうだということを報告。そのあと何をするかについて話した。いよいよ機械学習をやってみるようで、サンプルコードを紹介されて読み、実際に手を動かしてみることになった。

そのあとは業務に関係のない話として、Kaggleの進め方についてまたアドバイスをいただいた。Kaggleは競プロとは違ってコミュニティで知見を共有しスコアを伸ばすのが推奨されているので、いろいろな提出が公開されるらしい。聞いた感じでは、公開された提出に自分なりのアイディアを盛り込むことでスコアを伸ばすのだという認識。また1回の提出で1時間くらいnotebookを動かすのは普通にあることらしく、競プロとは全然違う時間感覚だなあという気持ちになった。昨日、特徴量を手当たり次第に放り込むということを書いたが、そういう「できるだけ様々な要素を考慮する」ことに関連して、Kaggleでは2つのモデルに結構な精度の違いがあったとしても、ある程度悪いモデルも含めて混ぜ合わせたモデルを作る(アンサンブル)のが結構効くようだ。これは自分の直感にかなり反していて興味深かった。

その後大学生協とコンビニに行って買い物をし、食事。そういえば2回目のワクチンを接種してから2週間が経過したため、fully vaccinatedと言ってよいだろう。帰宅して、業務を開始する気にならず(おそらく、今やっていることが終わったら機械学習という未知の領域に踏み出すことになるという恐れから)、しばらく本を読んでいた。

かくりよの宿飯」6巻読了。前の巻でストーリーが一段落したので、この巻は比較的まったりしていた。ところがまたラストになってきな臭くなって、5巻ではやり込めることができた敵キャラがまた姿を現した。一体どうなってしまうのか。またその直前、主人公と鬼神の大旦那の関係にかなりの進展があって、こちらは非常に健康に良かった。

7巻を手に取って読もうとしたが、急激な眠気に襲われ、布団に倒れこんで、午後7時くらいから午前0時半まで寝ていた。

夕方に14の1落ちが出ていたのはツイートを見て知っていたが、手元動画も撮影していたようで、投稿されていた。歴史的資料。

www.youtube.com

結局今日はインターンの業務を一切行っておらず、非常にまずい。まずいが、とりあえず日記を書くことにした。その間マラソンに関していくらか新しいアイディアが生まれたので、それも記しておく。

まず、最初の850ターンは収穫機を買えるなら買うという方針にして、179976413点。次に、将来のマスの価値として「生えるまでの時間」で重みづけしていたのを「枯れるまでの時間」としたところ、202885296点まで伸びた。提出時は21位とギリギリ順位表の2ページ目になっていた。

日記を書き終えてから、1時間だけインターンのコードを書いて、もらったリポジトリのコード読み・リファクタリングが完了した。一応もらった時のコードと出力が変わっていないことは常にチェックしている。これで次から機械学習か、と思ったのだが、その前にコードの出力を眺めていたところ、微妙に怪しい部分があった。明日のミーティングでちょっと聞いてみることにした。

ちょっとコードゴルフをし、ラノベの新刊チェックをして、午前6時前に布団に入った。ネット小説をチェックすると東方遺骸王の更新が来ていたので、読む。前の話から一気に数百年くらい飛んだようで、そういうのはかなり好きな展開である。人間の寿命の短さを感じる。また、かなり昔から出ていた紅美鈴らしきキャラは名前が違っていたが、便利のために改名したという形で、その師匠ポジなどではなく本人そのものだったことが明かされた。かなり膨大なバックグラウンドがついたことになり、感慨深い。誰かの感想に書かれていたが、原作でただの門番をしているけれど、実は(この作品の設定上は)屈指の長命キャラであるというのがかっこいい。

そのあと、流れで捜索掲示板を漁り、1作見つけて読みふけってしまった。20話もいかず完結していたが結構読みごたえがあり、2時間半ほどかけて読了した。

syosetu.org

かなり良い。コナンのストーリーは事件発生から解決までの間がほぼダイジェストになっていて、この作品の元となった部分の原作漫画を前半少ししか読んでいなかった自分はなかなかついていくのが大変だったが、それはそれとして少年探偵団と輝夜の関りが非常に健康に良い。輝夜がその美貌でモデルにスカウトされ、一躍時の人となるという設定も好み。ただそういう表面的なことだけではなく、ちゃんと底に一連の流れがあって、綺麗にまとまっているのも満足感が高い一因である。

明日の1on1は午後3時からの予定だ。生活を完全に破壊してしまい、慌てつつ午前11時前に就寝。

09/08(水)

午後2時、かけていた1度目の目覚ましで意識を取り戻す。二度寝するのはさすがにまずいため、根性で起き上がった。しばらくパソコンの前でボーっとした後、1on1が始まった。

昨日発見した出力の怪しい部分は、この後影響が大きいようだったらまた考えることにしましょう、という話になった。まあそういうものか。個人的には納得のいく処置であるが、その納得の理由を詳しく書くのは控えておこう。その後、火曜日に紹介されたサンプルコードの話になって、まだ読んでいなかったのだが、少し手ほどきを受けた。実はそもそもMNISTやImageNetが何を表すかもわかっていなくて、適宜ググりながら話を聞いた。サンプルコードは多少長くて少し骨が折れそうだと思っていたが、今日の話で出てきた部分が勘所のようなものなのだろうから、そこから周りを見ていけば何とかなりそうな気がしてきた。

また、業務に関係ない話として、自分の生活習慣が崩壊していることを申告した。このままではいつか絶対1on1に寝坊すると思ったからだ。まあもともと先方の予定を聞いて空いているところに入れていたので、もっと夕方にずらすならそれで特に問題ないらしい。そのあたりかなり柔軟に対応してくださるのが非常にありがたい。働きやすさを感じている。

1on1が終わったらまた寝ようと思っていたのだが、思ったより意識がはっきりしている。しばらくパソコンの前でグダグダした後、学食に行くことにした。雨が降る中クロックスで外出。帰ってきたらクロックスの中の汚れが足に移ったのか、足からひどいにおいがしてきて、かなりげんなりした。確か大学1年生の時に用意したものだから、もう4年目、さすがに買い替え時か。

帰宅してまたハーメルンを漁っていた。今やるべきことではないという思いが強いが、久しぶりにネット小説を読む体験というのは止めがたいものがある。結局今日のECRのちょっと前まで読んでいた。

こどふぉを開いたら、自分が2件のコメントで言及されたと通知が来ていた。見に行ってみると、Tシャツが当たっていたことを知った。Deltix Roundというちょっと前のdiv.1で上位100人にギリギリ入っていたので1着、さらにCGR15の31~500位にランダムで配られるので1着。これがこどふぉで獲得する初めての衣類となりそう。

午後11時半からECR113に出た。5完。

Dashboard - Educational Codeforces Round 113 (Rated for Div. 2) - Codeforces

Aはギャグ。Bは勝ちたいプレイヤー同士が順繰りに勝つように埋めればよいが、勝ちたいプレイヤーが1人または2人しかいない場合は不可能。2人の場合を見落として1WA。Cは最大値と2番目の最大値の差が1以下でなければならず、ちょうど1のときだけダメな順列が存在するので、求めて引く。Dは、街が道路でマス目に区切られていると考えると、ある長方形の対辺に乗っているペアを数えることになる。座標が106以下なのでそのままBITに乗せて、初期化はいちいち更新をロールバックしたが、座圧すれば1マス取得でよかったようだ。縦横両方にするのも少し面倒。

Eは難しい。トーナメント表の半分ずつ(準決勝の2分の1、準々決勝の4分の1……のこと)をsetで全通り計算するコードを書いてみたところ、k\le 4は爆速で終わるが、k=5のときが間に合わない。setに直接insertするのではなく、いったんvectorに溜めてみたところ、手元で4secをギリギリ下回ったが、CF環境が信頼できないので、もう少し根本的な改善をする必要があった。実は全通り計算するのは下からk-1段目まででよく、k段目については値の存在判定さえできればよい。ということで最後の段を特別扱いすることにしたら、k=5の場合もk=4までの計算で済むので爆速になった。

Fは、文字種を座圧したものが15万通りくらいしかないようなので、それを全探索するのかとも思ったが、毎回の判定が間に合わない気がして、一気にdpで計算するのかと考えていたら、コンテストが終わってしまった。TLを見た感じ、全探索した後毎回判定するので合っているらしい。

今日は結局インターンの業務を進めることができなかった。現実逃避のためにECR17を埋めた。

Dashboard - Educational Codeforces Round 17 - Codeforces

Aは、制約からO(\sqrt n\log n)を落とそうとしているのかと思い、O(\sqrt n)で解いた。約数列挙をすると、昇順の列と降順の列に分けて得られる。Bはソートして貪欲だが、実装ミスのWAを勘違いしてコードを大幅に書き直す羽目になった。Cは左と右から必要な文字の範囲を前計算して、被らないように尺取り。区間の端を含むかどうかの処理で結構サンプルを合わせるのに手間取った。Dはヤバそうな見た目をしているが、実際のところたった5通りの状態に対する遷移を全部書き下せば終わり。Eはfごとにまとめてその個数ぶんのBITを作り、取得を区間和で行う。x+rを昇順に持っておいて適宜個数を引いていく。

Fはヤバそうな見た目をしているが、木dpを書くときれいに遷移してくれて、特段変わった処理をする必要はない。Sに含まれるTを頂点のラベル付きで数えた後、Tに含まれるTを全く同じコードで数えて割ることでラベルなしの数え上げをするのは、半信半疑で動かすとちゃんとサンプルがあって感動した。ところがTLEが取れない。ケースを見ると、大きすぎて上のほうしか確認できなかったが、どうやらウニグラフで落ちているらしい。そこで手元でちょっと試してみると、ウニの中心が適当に設定した根以外の場所だと一気に処理が重くなっていた。次数が一番大きな頂点を根として扱うことにしたら、爆速で通った。想定解でも木の中心を見つけるということを行っているが、その後重複を省く方法が、割り算ではなく頂点の割り当てを一意になるようにルール付けするものだった。

午前4時前になって、ようやくゲノコン2021のD問題が公開された。問題文がかなり厳つくて、これまで3問の練習問題がなければ確かに参加者は大幅に絞られただろうという気になる。というか、僕はかなり絶望していて、C問題も2700点くらいを出す提出のブログ記事を読んだのに結局何もやっていないため、これから触れることはなさそう。

Genocon2021 ー DNA Sequence Analysis Challenge - AtCoder

朝方、ハーメルンの捜索掲示板をいろいろ見ていた。自分の大好きな作品で検索したりするのも面白い。自分の好みのジャンルについての捜索が出されているのを見て、いっちょリストアップしてやるかとも思ったが、大抵は過去の似たような捜索で出ている作品であるから、別段自分が言う必要性もないな……と思って止めたりしていた。布団に入ってからもしばらくハーメルンを読んでいたが、午前8時過ぎに寝落ちした。

09/09(木)

午後3時すぎに目を覚まし、またハーメルンを読み始めた。午後4時半に1作読了。「俺の家が幻想郷」。

syosetu.org

良かった。オリキャラの名前や最初数話の文体からいかにもな厨二臭さを感じるが、設定が良いためあまり気にならなかった。ミニチュア東方キャラとかいうどう転んでも健康に良い設定、素晴らしい。同作者の別作品に主人公が同じ名前のこれまた東方2次創作があったが、そちらはシンプルなオリキャラ幻想入りであまり興味を惹かれなかった。

続いて別作品を読み始め、午後6時にさらに1作読了。「美少女精霊たちに愛されたいと頑張ったら最強の精霊使いになっていた」。

kakuyomu.jp

無双ものを期待し、実際に無双していたのだが、主人公のどういう点が周りと違うのかは説明されていても、それがどのように強さに影響してくるのかにはほとんど理由付けがないように感じられた。まだ物語が始まったばかりだからだろうか。主人公とヒロインの絆を描くストーリーも、クライマックスのバトルシーンもいい感じではあったが、自分の最近の好みに特別当てはまっているわけではない。

またハーメルンの捜索掲示板に戻って東方の2次創作を探す。いくつか良さげなものを見つけては数話読んでやめる、を繰り返していたら、読み進められそうな古代スタートものを1つ見つけた。それを読み始めたが、午後9時半くらいに寝落ちした。

目を覚ましたら午前1時だった。昨日インターンの業務が一切行えなかったのを気にしていて、今日は頑張ろうと考えてはいたものの、ふたを開けてみれば夜中までずっと寝たりハーメルンを読んだりを繰り返していただけ。これはひどい。慌てて起き上がり、とりあえずatgolferの更新を確認してしばらくコードゴルフしていた。HikakinTVに短い動画が上がっていて、以前「チャンネル登録者数995万人から1000万人到達するまで生配信する」と宣言していたが、いつの間にか996万人になってしまったので土曜の昼間から生配信する、ということを言っていた。僕もチャンネル登録した。

午前3時から業務開始。今日はちょっとしたコードを書いた後pytorchのexamplesからおすすめされたコードを読んでいた。午前6時で上がり。

また少しコードゴルフをした。起きてすぐ書いたコードが縮められていたので、縮め返した。

atcoder.jp

81B→80B→79B。明らかな短縮ポイントがずっと残っていたが、ここを縮めると50msくらいTLをオーバーしてしまうようだった。Vimの補完の際にめちゃくちゃ長い文字列が候補として挙がってしまうのが問題。何とかして実行時間を縮められないかといろいろやってみていたところ、数値をコードに直接埋め込むこと、うまいこと改行を残すこと、掛け算の順番を変えることで数回に1回2000msを切るようになった。4ケースTLEしているので、全部2000ms以下に揃えるのは厳しいかと思いつつ提出したところ、1発で見事に通った。1つのテストケースに対して最大3回実行されるということもあるし、思ったより確率は低くなかったのだろう。とはいえ、その後3回出して3回ともTLEしているので、やはり運が良かったのは大きいか。

CFのTシャツをもらうためにsettingからADDRESSを埋めた。SOCIALという部分にも個人情報を書くべきかと思ったが、必要ないらしい。シャワーを浴びてゴミ出しし、ちょっとだけKaggleを進める。スコアの良い公開提出をコピーしてきて、自分で動かしてみていた。ここに自分なりの特徴量を増やしてうまくいけばスコアがよくなるということらしい。submission.csvを見ると、これまで自分が提出してきたものより行が多くてびっくり。自分のコードのどこかが間違っているのだろうか。それにしては、なぜ正しく採点されているのだろう。よくわからないが、その違いを見極めるには微妙に眠気があるので、今日は寝ることにした。

布団に入ってうっかり1時間ほどハーメルンを読んでしまう。明日は午後3時半から1on1で、この2日間の無みたいな進捗をメンターさんにお伝えしなくてはならない。起きられるよう祈りながら午前11時就寝。

09/10(金)

午後2時半の目覚ましで目を覚ましたが、あまりにも眠すぎるということで30分二度寝する賭けに出た。勝利して見事午後3時に起床。

YouTubeを見たら、HikakinTVのチャンネル登録者数が1000万人を超えていた。生配信はどうなったかというと、今日の昼ぐらいに急遽行ったものの、20分もせずに到達してしまったらしい。アーカイブを見たところ10分弱で1万人増えるというとんでもないペースで、HIKAKINのすごさを思い知った。本当は僕は、5万人増えるのに何日かかるんだろうかとかそんな長いこと配信できるのかとか、いろいろ心配していたのだが。

HIKAKINのこれまでの道のりを詳しく知っているわけではないのだが、より一般に、人が感極まっている様子に弱い。今日のHIKAKINは、直前まで普通の声だったのが、感情がある閾値を超えた瞬間に急にヘロヘロになるという、特に理想的な感の極まり方をしており、何度見てもうるっとくる。

午後3時半から1on1。今週は稼働時間としてはほぼ無だが、一応1on1の度に1段階以上業務を進めている。個人的にはたった数時間コーディングして終わるようなことは大した進捗ではないと考えているが、メンターの方からは思ったより進みが速いと言っていただいて、嬉しくなった。調子に乗らないようにしたい。進捗報告の後はこの後数日やることの確認を行って、1時間もせず終了。

様々な物事に対するやる気がちょっと出てきたので、メールを2通書いた。1つは4年ゼミの先生宛で、長期インターンを開始したことの報告。もう1つはサークルの顧問教員宛で、サークル代表を交代することの報告。さらに代表者交代届をまだ提出していなかったので、自分の分を書いて新代表に残りを埋めるようお願いしたりもした。これはここ数日やるべきこととしてずっと頭の中にあったので、解決できて満足。

夜、学食に行こうとしていたらインターン先からパソコンが届いた。ワクワクしながらとりあえず学食で夕食を食べ、帰ってきて開封

周辺機器は、会社のお金で買うこともできないことはないらしいが、その時はパソコンとともに会社に返却することになるので、自分で買って使うことにした。明日あたり早速買いに行きたい。キーボード、マウス、LANケーブル、延長コードは必ず必要なもの。あとはモニターとモニターアームも欲しいので、机の寸法など図ってから電気屋に行こう。寸法を測るためのメジャーが家にないため、それもまず買っておかなければならない。

今日はとりあえずパソコンのセットアップだけでもしておくかと思って、モニター1枚のケーブルを移し替えて起動してみたが、LANケーブルがないとネット回線に接続できなかったので、諦めた。

しばらく日記を書いてから、yukicoder 313に出た。全完。

yukicoder contest 313 - yukicoder

Aはよい。Bはびっくりするが、制約がギャグなので愚直に解ける。CはどのA_iでも立っていない最小のbit。Dは区間setの遅延セグメント木を書きかけたが、priority_queueでシミュレートして区間minのセグメント木でチェック、でよい。Eはdp。Fは構文解析。Gは、Eの考察をさらに進めると、買う・1回交換する・売るを繰り返すことになるのがわかり、最小費用流で解ける。つい最近もABCで最小費用流を見たので、しばらく無意識的に考察から除外していたが、作問者のツイートを見るにこの問題を作ってからABCで出たという流れだったらしい。負辺があるが、除去せずDAG上のDPでポテンシャルを求めて解いた。

しばらくパソコンの前で、朝方からは布団に移動して、ずっとハーメルンを読んでいた。東方オリ主古代スタートもの。オリ主が幻想入りする直前の現代の風景がかなり好みで、ちょうどそのあたりに差し掛かったので、舐めるように読んでいた。幻想入りしてから原作キャラと再会するシーンも好きだが、そのあとはだんだん興味が薄れていきがちなので、どうしようか迷う。最近読んでいた作品はこれ。

syosetu.org

午前7時くらいに就寝。明日は買い物。

09/11(土)

午後3時、起床。すぐに準備して、地下鉄に乗って駅前まで出る。

まず、ヨドバシカメラでLANケーブル・延長コード・キーボードとマウスを揃える。今使っているマウスがトラックボール式なのでできれば揃えたいと考えていたが、結構いい値段がするので、あえてガラッと変えてタッチパッドのついたキーボードを購入した。それでも4000円くらいしていたが、トラックボールマウスを買うよりは安いので即決してしまった。あとは前から欲しいと思っていたエアダスターも買って、合計1万円弱。ヨドバシカメラのポイントカードを出したら、クレカ機能が付いたカードに交換しないかと言われ、まあ勝手にやってくれるのなら……と思って頷いたら、機械の前に案内されてさあどうぞ!と言われキレそうになった。

実際にキレることはなくて、唯々諾々と個人情報を入力していたのだが、現在持っているポイントカードと情報が合わないらしい。店員さんが調べに行ってくれたところ、どうやら実家の情報が入力されていたようだ。ポイントカード自体も実家に届いてしまうらしく、さすがに面倒が過ぎる。このあたりで勇気をもって「やっぱりいいです」と伝えることができて、無事会計に戻った。そもそもヨドバシカメラは年に1回行くか行かないかのペースなので、ポイントが失効する前に使えた試しがない。還元率がどれだけ良かろうと無駄。

続いてモニターを選ぶ。ヨドバシカメラにもモニターやモニターアームが置いてあったが、なんだか思っていた値段よりも高い。モニターにスピーカーが付いている必要はないので、そういうものを売っていることが期待できるパソコン専門店、具体的にはドスパラのほうに行くことにする。が、ドスパラにもスピーカー付きのモニターしかなかった。

モニターアームについて店員さんに相談してみた。すでにディスプレイを置いていて、それの上に並ぶようにモニターを設置したいと言ってみた。可能ではあるようだが、ちょっと製品を選ぶ必要があるらしい。ポールを立てて、そこからさらにガス圧のアームを伸ばすようなものなら大丈夫だろうとの話。また、2枚設置したいということを言ったら、1枚用のものを2つ買うのもアリだと言われた。ともかく、目的に合致するものは実店舗には置いていないので、結局はネットで注文するのがよいとおススメされた。

仕方ないので帰る。せっかく駅前まで来たということで、スマホアームを設置している店舗に行ってチュウニズムの手元を撮影してきた。以下のリプライツリーにまとめてある。

帰ってきてすぐ製品を選ぶ。モニターアームは、結局2枚縦に並べられるものを2つ買って使うのが間違いないと思った。買ってから気づいたが、僕が選んだ製品だと上段のモニターが下段のモニターより奥に行ってしまうかもしれないし、さらに上にだけモニターを取り付けたアームは重心的に不安定で危険な気がする。肝心要のモニターは、15000円くらいを想定していたつもりだが、どうやら20000円を切る製品すら限られてくるようだ。サイズも決めていなかったのでかなり迷ったが、結局↓のモニターを2枚購入した。そこそこ大きくてそこそこ安く、VESA規格に対応しているのでちゃんとモニターアームに設置できる。

Amazon | HUAWEI モニターディスプレイ Display 23.8(23.8インチ/IPS液晶/解像度1920×1080/1年基本保証+2年無償延長保証/HDMI/ブラック)【日本正規代理店品】 | HUAWEI(ファーウェイ) | ディスプレイ 通販

あとはパソコンと接続するケーブルを1本で、総額45000円弱。競プロの賞金として得たAmazonギフト券で支払える額だったので、拙速を尊びそれで購入した。代わりに振り込みのためATMから降ろしてきたお金の行き場がなくなったので、また戻しておこう。これまでのお金遣いからするとかなり散財したなという印象だが、インターンでこれ以上の金銭を得られる予定なので問題ないはず。金銭感覚が追い付いていない。

モニターを選んでいるということをツイートしたら、某競プロerさん(匿名希望)からAmazonギフト券7000円分(も!)を送ってもらった。かなり突然のことで、非常にありがたい一方、こんなに貰って自分は何を返せるのかという気持ちになった。とりあえずメンションなど飛ばして感謝の気持ちを大々的に伝えようとしたが、匿名希望らしい。心の中で本当に感謝しているということを、ここにも再度記しておきたい。

午後9時からABC218に出た。6完。もう完全にダメ。

AtCoder Beginner Contest 218 - AtCoder

Aはよいが、短い書き方となるとわからない。BはPerl、そのあとRakuで出しなおした。CはC++で、愚直O(N^4)しか思い浮かばなかったので出したら1200msくらいで通った。結構攻めた制約だな~などのほほんと考えていたが、これが想定なわけはない。Dは座圧した後xを2つ選んでbitset。4secなので自信を持って出したが、これも想定ではなかったようだ。Eは打って変わって非常に簡単、最小全域木っぽいことをやるだけ。Fはなかなか難しくて、迂回路があるかどうかなど考えていたが、しばらくして答えに影響する辺が高々N-1本しかないため、毎回計算できることに気づいた。

Gが解けなかった。二分探索を一生考えていたが、全然合わない。最後に出した提出は2分探索を2重に行っていて、2ケース落ちた。8問体制になってからABCの600点に苦手意識がついている気がする。何とかしなければならない。

TLをチラッとだけ見たが、二分探索ではなかったらしい。それでさらにしばらく考えたら、ふとdfsを1回するだけで各葉に対して中央値が求まることに気づいた。それからも結構WAを重ねて、ようやく解けた。僕は優先度付きキューを2本持って、取り出したときにすでに考慮しない要素だったら無視する方針で書いたが、解説のようにmultisetを使って直接削除するほうが簡単か。さらにH問題を考えていたが、TLをちらっと見た瞬間にちょうどAlienDPとのキーワードが流れてきてしまった。まあ自力では不可能な気もする。upsolveは後回し。

コードゴルフ。AはVimを書いていたが2B負け。BはRakuに満足していたら普通にdcで縮められた。Cは面倒そうだなと思っていたところ下のHaskellコードがatgolferに流れてきたので、Rubyに直して縮めた。

atcoder.jp

Dも僕がコンテスト中に書いた方針(xを2つ選んでyをカウント)をRubyで書いたが、解説の左上と右下を固定する方針を試していないため縮むかもしれない。pythonはその方針で書かれているようだ。EはPerl。0とのmaxを取るのは$-に代入するしかないと思っていたが、先頭に'0'を加えて数値として解釈してもできるらしい。そちらの方法だと空白を1つ省けて縮む。以降は手付かず。

午前2時からFHC2021 R1に出た。

Facebook Hacker Cup - 2021 - Round 1

24pt取れば通過できるらしい。僕はA1A2A3とBを解いた。

A1はまあ、できる。A2を考察するときにA1をもう一度よく考えると、これはつまり'F'を無視したときに'X''O'が隣接するような場所の個数だとわかる。それを用いると、逆に隣接する'X''O'を両方含むような部分文字列の個数だけ答えが増えるということになって、A2が解ける。A3のため、さらにA2を考えてみると、だいたい\sum l\times rという値を求めていることになるが、実はこの値は加えて\sum l\sum r\sum 1、文字列の長さを持っておけば文字列を2倍する操作に対しても更新が可能。間で1つ増える可能性があるが、これは一番左・右にある'F'でない文字を追加で持っておくことで求められる。オーバーフローしていたがvalidationで落ちてくれたので助かった。

A3を解く前にBを解いていた。しばらく考えていたが、実はギャグで、左上と右上の値だけ増やせばOK。

朝方布団に入ってハーメルンを読む。案の定昨日まで読んでいた作品は微妙に飽きたので、別のものを1つ。しかしよくわからなかった。

syosetu.org

別の作品、これもまた東方オリ主古代スタートものを読み始めたり、過去に読んだハーメルンをちょっと読み返したりして、午前9時に就寝。

09/12(日)

午後4時半に起床。午後5時からOpenCupに初参加した。何のリンクを貼っていいのかわからないので、とりあえずCFで議論していた場所を貼っておく。

XXII Open Cup, Grand Prix of Dolgoprudny - Codeforces

ヤバかった。赤3人で組んで5完だが僕自身は1問も通せなかった。前のほうの問題を読んで概要をまとめていたが、どうやら非人間向けだったらしい。考察した問題はDとKで、DはMo's AlgorithmにsetのlogをつけてTLEしていたのを、チームメイトがvan Emde Boas treeでぶん殴っていた。Kは最終的に98チームが提出してAC数2という化け物で、僕も見た目が簡単なのに騙されて適当な解を投げ、考察を進めるたびに難しさを実感して結局放り投げた。他にチームとしてACできた問題は、そもそもまともに考察していないので、upsolveも何もあったものではない。

CFブログにあったDの解法は頭が良い。Mo's Algorithm中で自分より小さい要素の最大と自分より大きい要素の最小を取りたい。結局謎データ構造で\log\log Nになったが、実はDancing Linksを使って線形時間でできるようだ。削除を巻き戻すため、更新順序を良しなにしなければならない。どうするかというと、まずクエリのlでブロックに分け、各ブロックでデータ構造を初期化する。rの昇順に並べるのはMo's Algorithmと一緒だが、lのために毎回ブロックの先頭からlまで進めて(削除して)、クエリに答えたら即座にブロックの先頭まで戻す(削除を巻き戻す)のを繰り返す。Mo's Algorithmの計算量解析からして、このように無駄な操作を行っても高々定数倍しか変わらない。Mo's Algorithmの更新順をいじることで操作を単純にするのは見覚えがある気がする。

5時間椅子を温め続けた。終わってすぐTOYPROのコードゴルフ大会に30分だけ参加した。

TOYPRO(トイプロ)

なかなか独特な競プロ体験だった。問題文で与えられた変数を使って、サンプルを埋め込んだようなコードを書いて提出すると、対応する変数名の変数にテストケースの内容が代入されてジャッジされるようだ。しかし同時に、代入しない状態でのジャッジ(正常に実行が終了するか)も行われるようで、変数だけ用意していると落ちる。ほかの人のコードを見たわけではないので何とも言えないが、自分は用意した変数を即座に1文字変数に代入してコード長を削ったりした。

1問目からマルチバイト文字を扱っていてびっくりするが、どうにかこうにか2問目から5問目までゴルフっぽいことをして提出した。しかし順位表を見ると、どの問題もより短いコードが存在していたらしく、悔しい。

日本橋ハーフマラソン2021 増刊号が終わっていた。結局、火曜日の提出が最後になって、システムテスト前の順位は100位まで下がってしまった。終わった時間にTLを見ていなかったので解法を終えていないが、どうやら評価関数をうまく設定してビームサーチする問題だったらしい?僕のコードは評価関数が重すぎてただの貪欲が精いっぱいだったが、遷移を絞り込むと幅を増やせたのかもしれない。コードゴルフとしては-1で埋めるのが短いが、この問題では1000行より多く出力していてもACとなるらしい。sedc-1が最短となった。

ACPCの参加登録が始まっていたので、申し込んだ。

ACPC 2021(会津大学競技プログラミングコンテスト 2021) - connpass

午後11時半からCF CGR16に出た。

Dashboard - Codeforces Global Round 16 - Codeforces

ABCdDEFGを解いて12位、レートは2823→2952(+129)でhighest。大成功だった。

Aはよい。Bは2が必ず達成可能なので0と1を判定すればよく、簡単。Cは(0,1)を必ず切り離して、(1,1)(0,0)が隣にあったらそれと組む。どちらも左から貪欲に求められる。Dは、D1もD2も座る場所を貪欲に決めることができる。答えを求めるときは、毎回O(m)かけても間に合う制約だが、一応BITを作った。Eは葉からどんどん切り離していくとして、最終的にどこに繋げるかは考えなくてよい。

Fは、初期状態ですでに条件を満たした区間を取り除いて考えると、各aで分割された間にいくつかの区間が挟まる形になるので、そのまとまりごとに「左からいくつを左のaで取るか」を考えてdpする。dpのキーは、左右にあるaを自由に動かせるか、あるいは元の位置に戻す必要があるかの2×2通りだけ。実装を簡単にするために左右に番兵を入れたが、その値をintに収まるよう\pm 2\times 10^9にするとマズそうなので、わざわざlong longを持ち出してこなければならず、大変だった。

Gは面倒。辺を短い順に4本取ってきて、それぞれ1234とする。12が端点を共有しないなら、それらが答えになる。そうでなくとも、この4つの辺のどれか2本は端点を共有しないことがわかるので、考えるべきは(3,4)の組より長さが短いものだけ。それはどんなものかというと、*を1本の辺として(1,*)または(2,*)または(1+2,*)に限られることがわかる。ここで1+2は2本の辺からなるパスで、(1,2+*)(1+*,2)も適当に組み替えると(1+2,*)にできる。つまり、いまある辺のうち端点がuでもvでもないもののうち最短のものが取得できればよい。各頂点に対し、そこから出る辺(ともう一方の頂点)を短い順に3本保存してセグメント木に乗せて解いた。2つのデータのマージは、辺の先の頂点が重複しないように注意して計算する。辺の追加は簡単で、削除については、各頂点に対して優先度付きキューを持っておいて、そこから上位3つを改めて取り出す(削除された要素は無視)ことで再計算した。この部分については昨日のABC218-Gのようにsetを使ったほうが楽だったかもしれない。

Gのシステムテストが750ケース以上あってびっくりした。

FHCが終了した。出したものは全部通っていた。Cもちょっとばかり考えていたのだが、C\le 20という制約に気づいておらず諦めてしまった。また順位表にそこそこTimer Expiredがいたので何となく予想はついたのだが、手元で実行してstack overflowした人が多かったらしい。beetさんのブログに回避方法が書かれていたはずだが、もう見ることはできない。

HikakinTVに生配信直後の様子を撮影した動画が上がっていた。そのうち以下のシーンについて。SEIKINがHIKAKINのために急いで買ってきたケーキの話で、HIKAKINが「ホールじゃん」と言ったのをSEIKINが「当たり前だろ」と言ったのがかなり印象に残った。また店頭で頼んで文字を書いてもらったからSEIKINだとバレバレになったりしたことも面白い。

朝方日記を書いている最中にABC218-Aが縮んだ。今回の問題は'o''x'を区別する問題で、たまたま'No'には'o'が含まれ、'Yes'にはどちらも含まれない。というわけで、'Yes No'という文字列を用意し、Yesの上にカーソルがある状態で'o'または'x'を検索すると、'o'の場合はNoにカーソルが移り、'x'の場合は移動しない。その後カーソル下の単語を消せば答えが得られるという寸法だ。

atcoder.jp

週記(2021/08/30-2021/09/05)

08/30(月)

先週の週記は、文章を書きながら意識を飛ばしそうになっていたので、投稿してからは比較的すぐに布団に入って寝た。午前6時半だった。

途中、午前11時くらいに目を覚まして、ちょうど届いたAmazonの定期購入の荷物を受け取った後、少し布団でゴロゴロしていた。この時間に起きたら学食に行けるなあとか、注文した本が生協に届いたようなので受け取れるなあとか、そのようなことを考えていたが、結局また寝入ってしまった。

次に起きたのは午後6時くらい。寝ている間にSlackでDMが来ていて、sotanishyさんが次代のサークル代表に立候補してくださった。一応サークルの規則で、総会を開いて代表を決定することとあるが、正直そのためだけに通話をホストしたりするのはコミュニケーションコストが高いと感じているので、Slackのリアクション機能を利用した信任投票で決を採ることにする。コロナ前の碧黴さんが代表の時代は、通話で会議した記憶もあるし、僕自身借りた教室に集まって開かれた総会で代表に決定した経験もあるが、このあたりの文化はだいぶ消し去ってしまった。

atgolferの更新を追いつつコードゴルフする。最近あまり週記で触れていないが、今でもatgolferは数時間に一度確認しているし、短縮されたら取り返そうと努力している。今日も2つ更新されていて、1つは取り返したが、もう1つはどうにもうまくいかない。僕が初めに書いていたコードから変わっていない部分があって、そこは短時間で思いついた書き方なので縮みそうな感じはしていたのだが、思ったより頭が良かったらしい。

リストの途中の連続部分列を取得したくて、ただし取得したい位置が空の場合もある。このとき、例えばarr[3..2]は空のリストになるが、arr[3,-1]nilが帰ってきてしまう。また実は先頭にいくらかパディングしてarr[3..2]とできているのであって、本来はインデックスから3引いてarr[0..-1]という感じになるが、これだと-1がリストの末尾要素を指していると解釈されて、arr全体を取得してしまう。どうにも上手くいかなかった。

先週のABC216-Dの嘘解法が流れてきたので、縮めておいた。1回でも操作できること、つまり先頭要素に重複があることと、同じ筒の中に重複した要素がないことの2点を確認すれば通るらしい。

Submission #25466179 - AtCoder Beginner Contest 216

7セメスターの成績が出たので、いつも時間割と成績をツイートしているリプライツリーにつなげておいた。このリプライツリーももう3年半。こうやって何年も同じことを続けていると、いよいよTwitterアカウントが2つとない、失ったら最後取り返しのつかないものに思えてくる。もし今後何かの間違いでこのアカウントが凍結されたりしたら、自分はどうなってしまうのだろうかと、以前から不安に思っている。

先週金曜日のyukicoderのC問題の解説を見て、解いた。これはコンテスト当時思いつかなかったのだから仕方ないだろうという感じがあるが、もしこれがRatedに出て大敗を喫したらたまったものではない。

#694290 (Ruby) No.1658 Product / Sum - yukicoder

次に、こちらも解説を読んで、ARC216-Hを通した。

Submission #25470126 - AtCoder Beginner Contest 216

LGV公式ということでしばらく考えてみたのだが、自力では超大量の行列の行列式の総和を求められなかった。行列式の線形性というのは、各行各列に対しての概念であって、全く異なる2つの行列の和を考えられるような概念ではなかった。行列式には様々な意味づけがあって、この問題では置換による定義を採用して計算している。ARC054-C「鯛焼き」では、逆に置換による定義を使って問題を行列式の計算に落とし込み、計算は別の方法を採用していたので、対照的とも言えそう。

さらに置換を全探索して計算することにした後もいくらかステップがあり、順列ごとのdpを考えた後bit dpですべての順列をまとめて計算するくだりなどは、置換の符号もbit dpでちゃんと計算できる点など非常に美しいと感じた。出来上がったコードが非常にシンプルだったのも良い。総じて、凄まじい問題だった。

それからはしばらく本を読んでいたが、疲れを感じて布団に移動すると一気に眠気が襲ってきて、生活リズムの是正も考えて素直に寝ることにした。午前1時前だった。

08/31(火)

午前8時起床。

そのまま布団で、昨日読んでいた本を読み切った。「かくりよの宿飯」1巻。先週古本屋でシリーズ11巻をまとめ買いしたものに手を付け始めた。この作者は「浅草鬼嫁日記」で初めて触れて、本の内容というよりは設定や見せ場の作り方が好みと合っていたので、それ以来ほかの著作にも少し手を出していた。最初はファンタジーの本を書いていたようだが、人気シリーズは今名前を挙げた2つで、どちらもあやかし関連の話だ。ちゃんと面白かったので、今後の展開も楽しみ。

昨日嘘解法で縮めたABC216-Dがさらに縮んでいた。見た感じさらに条件を弱めたというか、そもそも先頭要素の重複があることをチェックする代わりに特定の文字列があるかをチェックしていて、いよいよテストケースハックの本領発揮といったところ。さらにafter_contestが追加されたらしく、もう縮むことはないだろう。まあこれもAtCoderコードゴルフをする宿命か。

学食に行って昼食を摂り、注文していた本を受け取った。今日は6冊。どれもかなり楽しみにしていた本なので、早く読みたいところだが、昨日から手を付けたシリーズも読みたい。どうすればいいものか……。

とりあえず今日買ってきた本の中から「現代社会で乙女ゲームの悪役令嬢をするのはちょっと大変3」を読み始めたが、昼下がり急に眠くなったので、耐え切れず布団に倒れこんでしばらく寝た。

午後1時くらいに意識を落として、次に目を覚ましたのが午後5時だった。アナログ時計は午前午後がわからず、外が微妙な明るさだったため、さては朝の5時か!?と思ってうろたえたが、ちゃんと確認すると全然そんなことはなくて一安心だった。

そのままずっとラノベを読んでいたが、午後8時半くらいになって、昨日サークルSlackに投稿した新代表のアンケートの信任が過半数を超えそうになっていたので、アカウントの権限付与などの作業をsotanishyさんと一緒に行った。特にGmailアカウントは、一度ログインしてもらってこちらから認証しなければならないため、2人の手が空いているときに行ってしまう必要があった。それ以外は順調に進み、定期的にサークルのメアドを確認してもらうことだけ伝えて終わり。ICPCICPCの、新歓は新歓の時期にまたいろいろ伝えることになるだろうが、通常の業務はこれくらいとなる。

日付が変わったあたりで「現代社会で乙女ゲームの悪役令嬢をするのはちょっと大変」3巻を読了。今巻も非常に面白かった。単純なのでお嬢様が表舞台に立っているだけで面白く感じられて、その意味では今巻の卒業コンパのシーンや、特に桂華タワー落成式のシーンはWeb版から好みの部分だった。恋住政権が発足してから、以前のように政治にバリバリ関わることが難しくなったお嬢様だが、今後も経済のほうで活躍する姿を見たい。

明日から始まるインターンの初日の予定がメールで知らされた。同じ時期に業務を開始する面々や社員の方々との顔合わせ、社長からのお話もあるため、ありったけの社会性を用意して臨みたい。

布団に入って少し本を読んだが、すぐにやめて午前4時就寝。

09/01(水)

午前9時半起床。急いで食事し、オンラインの入社式に備えて上半身だけ着替えたりノーパソを壁に向けたりしていたら、ギリギリの時間になった。

午前10時から開始。全体向けの会社の説明、個人向けの説明、インターン受け入れ先の部署とお話、メンターの方と1対1でお話、と今日は一日喋る日だった。一応仕事に参加するにあたっての必要最低限のアカウントをセットアップしたりはしたが、逆にそれ以外何もできていないのに金銭が発生しており、かなり困惑する。早く成果物を作り出したくてたまらなくなってきた。午後7時で上がり。

終わってからしばらくは微妙な眠気で動けなかったが、何とか身を起こして学食に夕食を摂りに行った。帰ってきてからは本を読んだり動画を観たりしていた。

TSGがAnarchy Golfを使って小さなゴルフ大会を開いていた。特に参加はしなかったのだが、一応問題だけ見ると、コラッツ問題で与えられた数が1になるまでの経過を出力せよという問題だった。dcのコードが提出されていて、念のため確認したところ、これまでAtCoderで僕が使っていたコードより1B短くなっていることに気づいた。かなりびっくり。焦って2問ほど縮めた。

http://golf.shinh.org/reveal.rb?Collatz+Problem/tails+%28Carlos+Gutierrez%29_1332227477&dc

Anarchy Golfにいつの間にかJellyが入っていた。Unicodeで見ないと何もわからない。わけのわからなさでいえばgs2も似たようなものだが、Jellyは一応Unicodeの形に基づいて設定されているような命令もあるから、そこの違いは大きい。

しばらくなろうを読み返していた。以前に読んだなろうは、自分の好きなシーンだけつまみ食いすることができるので、読み返すのは結構好きである。実家にいるときはラノベもそうやって少し読み返したりしていたのだが、仙台に来るときに既読本はほぼ置いてきたし、今は数か月おきに読み終わった本を送り返さないと本棚に入らなくなってしまうので、ラノベを読み返す機会は帰省のときのみと極端に減ってしまった。

8月の読書記録をツイートした。先月は結構頑張って読んだつもりだったが、それ以上に本を買ってしまった。まあ、本は買えば買うだけよいということを常々思っているため、問題はない。

布団に入ってしばらく本を読み、午前1時半就寝。

09/02(木)

午前11時起床。午前10時からSRMがあったらしいが、さすがに早朝すぎて不可能だった。着替えて学食に行く。雨が降りそうではあったが、天気予報は40%だったのでそれを信じ、原付に乗って行った。この時間帯は道が混んでいないため、自分のような怖がりでも乗ることができる。

1万円札の新しいデザインが発表された発表されたのではなく印刷が開始された(2021/09/06追記)。以前のデザインは2004年から使われていたらしい。ところで、1万円のことを諭吉と呼ぶのはかなり自然な表現に感じられて、実際本などでもたまに目にすることがあるが、これは1万円札の肖像画福澤諭吉になってから登場した表現だったのか。たった17年前のことだとは思えないくらい広まっている……というようなツイートをしたら、実はその前の1万円札から福澤諭吉だったらしい。1984年からで、都合37年間だった。それなら納得だ。

今日は午後1時からメンターの方とまたお話をした。実は昨日のうちに、この後しばらくやることを決定していて、それに関することを重点的に話した。また更にいくつかのサービスでアカウントを発行してもらい、いよいよ自分の手元にコードを落としてきて動かしてみることになった。ちょっと環境を整備した後、さらに別の人と話す必要性を確認して、そのためのミーティングが明日にセッティングされ、今日は終了。午後3時だった。手元にデータを落としてくることくらいはもう可能なので、そういう準備をできるだけ進めておく。

思ったよりバリバリ機械学習をすることになりそうでビビっている。メンターの方に手ほどきを受けることになっているが、さすがに基礎的な事項くらいは自分で抑えておくべきだと感じ、とりあえずKaggleにアカウント登録をした。コースがいくつか用意されているので、これを手当たり次第に埋めていこうと思う。まず最初にPythonのコースを終わらせたが、さすがに全部既知の事項だった。最後のボーナスレッスンでTitanic Tutorialというコンペに提出を行ったが、今度は逆に知らないことだらけだった。どこからランダムフォレストが生えてきたのか一切わからないが、とりあえずデータは生まれたので、提出できた。

次にIntro to Machine Learning。こちらは結構勉強になった。いろいろなブラックボックスの使い方を学んでいて、中身が知りたいという気持ちもあるが、実際のところ機械学習の詳しいアルゴリズムを知らないと、むしろ知っていてさえ中身を見てもどうしようもないだろうとは思うので、とりあえず今は何があって何ができるかを知っていきたい。pandasのDataFrameをいろいろいじくりまわしているが、かなり柔軟な使い方ができるようで、とりあえずそれを重点的に学びたいとの思いから、次のコースはPandasにした。

このあたりで、改めてインターンのための環境構築を進める。pythonの必要なモジュールをpipで入れる作業をしていたら、どうにもtorchとtransformersがエラーが出て入らない。こういうときはエラーで検索すればいいんだ!と思ったが、見るとPythonのバージョンを下げましょうと書いてあったり何も出てこなかったりして、非常に難しい。やはりcygwinでやっているのが悪いということで、これを機にWSLに乗り換えることにした。

WSLを入れて環境構築。といってもcygwinの設定をいろいろコピーしてくるのが面倒になってきたので、WSLを使うのはインターンの間だけということに決めて、とりあえずPythonの環境だけ整えた。ちゃんとtorchもtransformersも入って安心。しかし日本語ファイルが全部文字化けしている!文字コードを変えるのはよくわからないし、いったん全部ダウンロードしなおしかな~とも思ったが、冷静に考えるとフォントが日本語対応していないだけだった。調べると、コンソールで使う日本語対応フォントでRictyというフォントがおすすめされていたので、それを入れておいた。

GitHub - kudryavka/Ricty: Ricty --- fonts for programming

あとは.vimrcを書いたり、カラースキームを適当に決めたりして、何とか見られるようにはなったのではないだろうか。

合間合間で本を読み進め、1冊読了。「かくりよの宿飯」2巻。今巻も面白かった。主人公は基本的に他人(他妖?)を悪く言わないので、そのお人よしさがちょっと気になることもあれど、基本的には好印象。そういうところがほかのあやかしに受け入れられていく様が描かれていて、明るい未来を感じる。

夜中、opencupに参加する集まりに招待された。印象としては、やっとのことで赤の山に登ってみたら、下からは見えなかった頂上に大量の人がいて、みんなさらに上を目指していた、という感じ。りんごさんの名言「赤にいかないうちは、典型も解けていないという証拠なのでどんな問題がでても文句を言わずに解きましょう」が思い出される。つまり、今ようやくある程度の典型を学んでスタートラインに立ったということ。何とか食らいついていきたい。

布団に移動して少し本を読み、就寝。午前6時半だった。

09/03(金)

午後2時起床。午後3時に大学生協が閉まるので、起きてすぐ向かった。昼食を確保するつもりだったがパン類がほとんど売り切れてしまっており、残っていた謎の総菜パンを購入。これだけでは足りないと感じたので、帰りにコンビニに寄って追加で菓子パンやおにぎりを買った。

生協の総菜パンは思ったより美味しかったが、しょっぱいものが美味しく感じられているだけにも思える。塩分不足かもしれない。

インターンの昨日の続きとしては、もう少しミーティングしないと手が動かせなさそうなので、それを待つことにして、Kaggleのコースを進めた。今日はPandasのコース。記法があまりにも柔軟すぎてむしろよくわからなくなってしまった。あとgroupbyの挙動がよくわからない。それっぽく書いたらそれっぽく動きはするのだが、自分で何かをやりたいとなったときにうまくできる自信があんまりない。

午後3時から3時間かけてコースを終わらせると、ちょうどミーティングの時間になった。業務について前任者から引き継ぎを受けるのが1時間、メンターさんとお話しするのが1時間。これまではミーティング以外何もできなかったが、引継ぎを受けて、とりあえず何をやればいいかが何となくわかってきたので、これからは自分でいくらか手を動かすことができる。

またメンターさんとのお話しでは昨日始めたKaggleを話題に取り上げ、Kaggleへの最初の取り組み方のようなふわっとしたアドバイスが欲しいとお願いした。聞くところによれば、僕はコードの読み書きがそれなりにできるはずなので、最初からコンペに出て人々の取り組みを観察したり、提出して自分の順位の変動を見たりするのが良いらしい。そう言われるとかなりやる気が出てきた。

しかしまあ、とりあえず今はインターンのコード読み書きをやってみたいので、そちらに注力する。実行に6分くらいかけたコードが最後のデータ書き出しの部分の文法エラーで落ちてしまって非常に辛かった。ちゃんと小さいケースでテストするよう心掛けたい。そうやって格闘していたら午後9時になったので、中断してyukicoder 312に出た。

yukicoder contest 312 - yukicoder

6完。Aはよい。Bは00が許されていないのに気づかず1WA。ここでk乗根を二分探索で計算するコードを書いたのだが、この後D問題でも使うことになって面白かった。オムニバス形式なので特に意図されたことではなさそう。Cは素因数ごとに独立になると勘違いして1WA、grundy数を直接計算して通した。grundy数はそんなに大きくならないだろうと思って64bit整数のbitを立てつつ計算したが、実際必要な範囲では最大19にしかならないので、これで十分。

Dは難しかった。二分探索をするのはよいが、累乗数を重複なく数えるのに手間取った。最初、素数乗の数を包除原理を用いて数えようとしたが、WA。3乗以上であって平方数でない数を全列挙したあと、改めて平方数を数える(ここで2乗根を計算する)方法で通した。Eはケイリーの公式でM=N-1を計算してそこから戻す……ということを考えたが全然ダメ。しかしケイリーの公式を使うのはよくて、連結成分ごと一気に遷移するようなdpを書いたら3乗になった。Fは隣接する値が異なるマスに対応してグラフに辺を張り、そのDAGの最長パス……としたがWA。隣接していないマスの値の大小関係も保存されなければならないことに気づいていなかった。値が小さくならないようにするには1から順に値を確定していけばよくて、DAGの作り方からこれはトポロジカル順序にもなっているので、正しく定めることができる。

そのあとGを考えていたが解けなかった。この問題にはあまり関係がなかったが、行や列を一気にflipする操作で黒に揃えられるのは全ての2x2正方形で黒マスが偶数個存在することと同値、というのは以前も見た覚えがあるし、ちゃんと覚えておきたい。今日も同じことを考えていたが、証明をつけるのに手間取った。

最近「やばいクレーマーのSUSURU TV」にハマっているが、本人がカバーして動画を出したのを知った。非常に出来が良い。

夜中、またインターンのコードと格闘を再開した。リモートワークでかなり自由度高く働けるので、この時間にコードを書いていても全然平気で給料もちゃんと発生する。かなり楽しい。しかしだんだん頭の働きが鈍くなってきて、この状態でのコーディングに対価が発生するのはなんだか申し訳なくなってきて、午前2時半くらいに切り上げた。

寝ようと思ったが、Kaggleも少し進めておこうかという気分になって、参加するコンペを適当に決めて問題を読んだ。「Optiver Realized Volatility Prediction」というやつで、金融に関する値を予測せよということらしい。データの内容や公式のチュートリアルを読んでいたが、英語にかなり壁を感じた。慣れていないためか競プロの問題文を読むのとは全然勝手が違う。結局最後まで読み切ってもよくわからなかったので、また明日取り組むことにした。

Optiver Realized Volatility Prediction | Kaggle

布団に移動して読書。1冊読了した。「かくりよの宿飯」3巻。冒頭ちょっと剣呑なシーンもあったが、その後は終始のんびりと進行。登場するイケメン男性キャラクターの振る舞いを女性主人公の視点から見て可愛がったりしていた。しかしラストシーンがかなりとんでもないことになって、4巻に続く!と終わった。どうなるのか非常に心配している。

4巻もちょっと手を出して読み進めたが、いい加減眠たくなってきたので、午前6時に就寝。

09/04(土)

午後1時くらいに目を覚ます。二度寝するつもりだったが、うっかりスマホを触ったりしてしまい、そのまま眠れなくなってしまった。今日は生協の冷凍弁当が届く日のようなので、午後3時からは起きていなければならない。布団でゴロゴロしていたが、午後4時くらいになってようやく身を起こした。今日は何をしようかしばらく迷って、Kaggleの昨日の続きをすることにした。昨日はこの公式チュートリアルみたいなものを読んで、読解が終わっていなかったのだった。

Introduction to financial concepts and data | Kaggle

何度か読み直して、ようやく理解できた。10分間の情報が与えられるので、次の10分間についてのある値を予測せよという問題で、チュートリアルの提出では与えられた10分間の情報からその10分についての値を計算して答えとしているようだ。それでも多少のスコアは出る、ということらしい。

やることは分かったので、とりあえず何か提出してみたい。チュートリアルのコードをそのまま出すのも味気ないので、自分なりに何かコードを書くことにした。Parquetという初めて扱うデータ形式が出てきて、あんまりよくわからない。どうやら与えられたデータがあまりに大量すぎて、1度に全部読みだすのはメモリの関係上やめたほうがいいらしく、いくつか区分けされている中で順々に処理していくことになる。

とりあえず1つだけ読み出してそれっぽい特徴量を計算してみた。あとは学習だが、今回は連続値を予測しなければならないので、適当にモデルを調べて、最初に回帰木のランダムフォレストを試してみることにした。その中身については全然知らないが、とにかくfitpredictのメソッドを呼び出してみると、それっぽい値が出ている。csvファイルに書き出して初めての提出を行った。提出してから20分くらい待ったら結果が帰ってきた。

つらい。再度notebookに戻って1文字消し、もう一度セーブして提出。また20分かけて、ようやく正しくスコアが得られ、順位が付いた。チュートリアルのコードよりも精度が悪いらしくてかなり下のほうだが、まあ最初だしこんなものだろう。試しに読み出すデータの区分を5個に増やしたら、大幅にスコアは上がったものの、相変わらずチュートリアルのコードに負けているため、順位的にはほとんど変わりがない。データの区分けは112個あるのだが、5個読み出して処理するのにも2分くらいかかっているので、全部やるのは気が進まない。そういう待ち時間がいちいち発生するのはあんまり好きではない。

スコアを上げる方法が全然わからないので、他の人のnotebookを読むことにした。1回の実行に70分以上かけているらしく、ヤバ……という気持ちになった。そうこうしていたら午後9時になったので、ABC217に出た。

AtCoder Beginner Contest 217 - AtCoder

8問体制になって初めて、ようやく全完できた。

AはAWKがよい。BはRakuで集合の引き算を行った。CはPerl。ABC142-Cとまったく同じコードを書いた。ここからC++で、Dはset。Eはちょっとびっくりするが、優先度付きキューとキューで管理すればよい。Fは区間dp、重複をうまく弾けておらず1WA。各区間について一番左の要素のペアを固定して考えるとよい。Gは、空のグループを許容する場合の数が、あまりが同じ人数などを考えると簡単に求まって(一旦箱を区別して最後にk!で割る)、そこから包除原理で答えを出した。Hはslope trick。maspyさんの記事を読みながら書いた。スタート位置が0と決められていることに気づかず、サンプルが合わなくてしばらく悩んでいた。

atcoder.jp

コードゴルフをする。Aは最初に提出したものが今も最短。Bは文字列のxorを使うのが短いらしい。Cは上の問題の最短コードをコピペ。DはC++を頑張って縮めた。endを指すはずのイテレータにアクセスするとなぜか1が返ってきたので、よくわからないがそのことを仮定したコードを出したら全ケース通ってびっくり。

GをPyPyで縮めているとTOKI Regular Open Contest #22が始まったので、出た。

https://tlx.toki.id/contests/troc-22

5完18位でレートは2588→2596(+8)。途中D問題が解けたときになぜかD問題だけサイトのエラーが出て提出できなくなってしまい、非常にイライラした。それでも何事もなくRatedになってしまい、びっくり。

Aは0があるかどうかを見る。Bはabcabc...を出力すればよい。Cは文字列を2文字になるまで操作した場合のスコアが一意になると気づいて喜んで実装したが、実は操作を途中でやめてもよかったらしい。そちらの解法は操作によって消す部分文字列を決めるdpで、遷移を高速化するために次の先頭となる文字で分類して値を持っておく。Dは二分探索で、ある番号以下の学校だけで全員が通えるかを判定するには多始点ダイクストラをすればよい。

Eはちょっと面白かった。先頭から二分探索して01が切り替わる境界を見つけるのを2回行い、axをそれぞれ求める。二分探索では、まず範囲として2べきを順に試し、次にその範囲内で通常の二分探索を行うので、都合4回、つまり最大4\log 10^9\gt 100くらいの質問回数が必要に見える。ここで、試す範囲はaに対応するものよりxに対応するもののほうが真に大きいため、xについてはaの値の続きから試していくことにすると、二分探索の回数が1回減って3\log 10^9\lt 100回くらいの質問回数で答えがわかるようになる。あとはb\lt 2xからbを求めて、最後にyを求める。baxから求まることに気づいておらず1WA。

ABC217-Gのゴルフの続きをする。PyPyでは負けてしまったので、Crystalを使ってみる。複数の値を出力するのがなかなか難しくて、どうやらjoinする必要がありそう。これだと出力の長さでPyPyに勝てなかったが、dp配列の埋め方を縦横逆にすると、毎ループの最後に1つずつ値を出力すればよいことになって、pで簡単に書けた。昨日入れたWSLにCrystalをインストールできたので手元でCEやREの様子を見ながらコーディングしていたのだが、AtCoder上のバージョン0.33.0と手元のバージョン1.1.1でもまたいくつか違いがあって大変だった。

また本を1冊読了。「かくりよの宿飯」4巻。前巻のラストシーンでとんでもないことになった主人公だが、なかなかたくましく生きている。さらに味方キャラがすぐ助けに駆けつけてくれて一安心。シリーズ最初のほうでは主人公は鬼神の大旦那に対してつんけんした態度をとっていたが、だんだん溶けていっているのもいい感じにニコニコできる。女主人公の視点で見ているので、溶けているという表現もちょっと違和感があるか。大旦那の良さがわかってきた、という感じ。

午前6時就寝。

09/05(日)

午後2時くらいに目を覚ます。またしばらく眠気の様子を伺いつつ布団でゴロゴロしていたが、やはり眠れないようだったので、今日も午後4時くらいに布団から出た。

昨日のABC217-Dは、Pythonのarrayとinsertを使ったコードでも通っていたが、C++コードよりは長かった。起きてみると自分のC++コードが縮められていて、どうにもこれ以上縮みそうにないので、改めて愚直にinsertするコードを考えてみる。Crystalでも同様のことができるのではないだろうかと思って書いてみると、通ってしまった。しかもコードがC++より短い。さらに何度か提出を繰り返して、111Bまで縮めた。

このように愚直なinsertが通ってしまうのはなぜだろうかと考えた。何か特殊な実装をしているわけではないだろうし、実はC++でも普通にinsertで通るのでは?と思って書いたら、見事に通ったので、特に不思議でもなんでもないようだ。ただPythonの通常のlistを使うと通らないので、型を制限することによるメモリ効率の向上が定数倍高速化に大きく寄与しているのだろうと思っている。

atcoder.jp

先週日曜日にLibrary Checkerに立てたissueがcloseされた。僕がissueの文面で提案していたケースがそのまま入ったらしい。実際に作業してくださった熨斗袋さんに感謝。

Add a test case to multipoint_evaluation by noshi91 · Pull Request #706 · yosupo06/library-checker-problems · GitHub

多点評価のハックケースをLibrary CheckerのGitHubにissueとして上げておいた。

週記(2021/08/23-2021/08/29) - kotatsugameの日記

午後6時からRECRUIT 日本橋ハーフマラソン 2021〜増刊号〜に参加した。

RECRUIT Nihonbashi Half Marathon 2021 (long) - AtCoder

まだ開催中のマラソンコンテストなので何も言えないが、一瞬だけ1位を取れた。

何も言えないのでこの間の時間は一気に飛ぶ(この間僕がコンテストに取り組んでいたということくらいは書いてもいいだろう)。午後11時半からCF #742 div.2に出た。

Dashboard - Codeforces Round #742 (Div. 2) - Codeforces

全完7位。

Aはよい。Bはaa+1かだと思っていたが、XORを合わせるために追加する要素がちょうどaの場合が困るらしい。サンプルにあって助かった。このような場合も、十分大きな2のべき乗を足すことでa+2要素で実現できる。Cは2つの繰り上がりを持つ桁dp。Dはまず各桁を10のべき乗に分解して、足りなければ小さいほうから10分の1にしていく。

Eは面倒。非減少部分列への分解を管理するのは、setに区間の両端を入れれば可能。求めるべき場合の数について、各要素に対してそれを終端とする非減少部分列がいくつあるかを数えると、それらの値はちょうどのこぎりの歯のような形のギザギザになる。つまり、傾きが1で定期的に1に戻るような値の列となる。数列の値の更新があると、このギザギザがある区間で一様に上がり下がりするだけの変化をするので、区間加算の遅延セグメント木で書ける。取得は当然区間和だが、一番前のギザギザは中途半端に取得されてしまうので、スタートを1にそろえなければならず、そこだけ区間を管理しているsetを見て補正する。僕は一番後ろも補正する必要があると思ってしまったが、その必要はなかった。

Fは謎。マークされたマスの周囲の空きマスは偶数個でなければならず、それらに1と4の数字が同じ回数だけ出現している必要がある。空きマスが2個の場合はその2マスに書かれる数字が異なることがわかるので、これを2部グラフの辺と見て奇閉路をチェックするような解き方をしたいが、空きマスが4マスの場合が難しい。特別扱いして、周りがある程度埋まったらうまいこと辺を張る、という感じで解けないかと思っていたが、そんなにうまくいかなそう。良い計算量の書き方が思いつかなかった。しばらく考えていると、ふと、空きマスが4マスの場合は斜めの位置関係のマスの組が全部互いに異なる数字になるように辺を張ってよさそうだと気付いた。そこが同じ数字になる必要があるケースは存在しないと思ったのだ。実装して投げたらpretestには通ったが、改めて考えてみると証明が回っていないことに気づいた。辺にはグリッド上でまっすぐな辺と曲がる辺があって、斜めの位置関係、つまりあるマスの上と左のような位置関係の2マスを結ぶときには曲がる辺を奇数回通らなければならない。しかしまっすぐな辺を通る回数の偶奇がわからないので、数字が同じか違うかはまだわからなかった。

Fはシステスに通ってハッピー。今回のセットは僕が本番で書いたコードより頭が良い解き方がいくつかあるようで、A問題はUとDを入れ替えているだけというのはともかく、Cで偶数桁と奇数桁を独立に考えたらただの足し算とみなせるのは感動した。

Fの証明が流れてきた。グリッドを外と内に分けて考えることで、上で述べたまっすぐな辺を通る回数が偶数であることがわかる。すると、斜めの位置関係の2マスが結ばれるときは合計奇数本の辺をたどっていることになるため、その2マスに書かれる数字は異なる。

今日の夕方縮めていたABC217-Dが1B縮んでいた。insertをまとめて書くことに執着していたが、<<演算子を使えば末尾への挿入が簡単に書けるので、分けることでさらに短くなるらしかった。

かなり昔の問題のゴルフをしようとした。フローを流すのでnetworkxを使おうと思ったのだが、入力形式が正しく守られていないようで、一度全部読んでsplitする書き方をしたらC++より長くなってしまった。ちょっと調べた感じでは、改行が正しいものよりも多いケースと少ないケースがそれぞれあるようなので、余計な空行があったり末尾に改行がなかったりしているのだろう。

Submission #25641840 - 九州大学プログラミングコンテスト2014

別に土日が休日であると意識していたわけではないが、結果的にこの2日間はインターンの業務を進めなかった。せっかくなので、もっとコードを書いて貪欲に稼いでいきたい。