2021年9月29日水曜日

Codeforces Round #744 (Div. 3)

  pretestはFまで。Gを考えていたら睡魔に襲われてしまった。


コンテスト後のツイート







 

 今更ながらツイートの埋め込み機能を使ってみたけど、見やすいか? というとどうなんだろう……。

 Eは、E1とE2で別の問題です、と書かれているのに、同じ解法で貪欲に辿り着くというのが面白かった。
 Gは考え方は間違ってなくて、bitsetを使ったら通った。bitset、最近使ってなかったから忘れていた。

2021年9月28日火曜日

AtCoder Beginner Contest 220

 Fまで六完。Fは全方位木DPのライブラリを用意していなかったのが良くなかったか。Eは面倒な解法を選んでしまったかと思ったが、良い解法と大差なかったのかな。

コンテストへのリンク

G - Isosceles Trapezium

 解法ツイートを見てAC。
 ポイントは、

・等脚台形は上底と下底の垂直二等分線が一致する。

 ということ。
 思いついても良かった内容ではあるけれど、時間もなかったし仕方ないかなぁ。

 なお、自分は、垂直二等分線を「方向ベクトルとx切片」で表そうとしたが、PythonのFractionモジュールを使ったところ重くなってしまいTLE。
 分数を、mod 10^9+7で表してACした。

 これだと、異なる二つが一致する可能性があるので良くないんだけど、どういう実装が良いのかなぁ。gcdを使うのが普通なのかな。

2021年9月25日土曜日

yukicoder contest 314

 最初の二問を見て、30分以上は考えていたはずだけど、分からず眠気に負けてしまった。


No.1680 Sum and Difference

 解説見てもちょっと悩んだけど、解説の方針でAC。

 とりあえず、二変数の問題なんだから、xy平面に描いて考えるべきだった、というのが反省。しかし、それでも解けるようだけど結構難しい。

 解説のように置換して45度回転しても、X=x+y, Y=x-yの偶奇が一致するときにx, yが整数になるというのがそれほど自明に思えなかった。
 偶奇が一致すると分かれば、共に偶数、共に奇数で場合分けして数え上げれば良い。

No.1681 +-*

 解説AC。
 +とーが打ち消すことは気付いたけど、その後が分からなかった(A[l:r]*係数みたいな形になりそうな気がして、それだと二乗かからない? とか思っていた)。
 言われてみればという感じではあるけど、結構難しい。


(解かれている人数を見るとDまではACすべきなんだけど……)

yukicoder contest 315

 コンテスト中はCまでしか終わらず、コンテスト後に自力でEまで。 
 最初Bが分からなくなってぼーっとしてしまったせいなんだけど、CDEは典型なんだからそっちを見るべきだったよね。こういう感じでやる気をなくすのは良くない。


No.1689 Set Cards

 bit DPが自然だと思う。
 ただ、想定解法は包除原理だった。

 以前も、bit DPで解ける問題の想定が包除原理だった問題を見たことがあったと思う。どちらも部分集合を扱うから当然といえば当然なのかもしれないけど、この二つが結構似ているというのは頭に入れておきたい。

2021年9月21日火曜日

Educational Codeforces Round 114 (Rated for Div. 2)

 pretestはDまで。コンテスト終了間際にEの大体の考察はできた。
 システムテストでDがMLEで落ちたけど、setに突っ込むものをtupleからhash(tuple)に変えて通した。(衝突させるテストケースは作れるだろうけど)


E. Coloring

 良い行列の作り方は、

・一行目を決定→n行目はn-1行目の反転
・一列目を決定→n列目はn-1列目の反転

 で全てを網羅できる。また、その方法で作ったものは全て良い行列になる。
 ただし、それだと市松模様が重複するので、その場合を引かないとダメ。

 実装は結構大変なものになってしまった。

・x=3, y=3で1
・x=x, y=5で0

 とかがあると、「一列目を決定→……」の操作では矛盾するので作れないのだけど、そういう、「この操作でやろうとすると矛盾」というのを管理するため、「一列目が1のときと矛盾しないものが何個で、0と矛盾しないもの何個か」を管理する。

 それが矛盾しないときにだけ計算する、という感じでやった。

2021年9月15日水曜日

AtCoder Beginner Contest 218

  Fまで六完。



G - Game on Tree 2

 しばらく解説を見ても理解できなかったが、落ち着いて考えたら理解でき、AC。

 コンテスト中は、中央値を求めるのだから答え二分探索だろう! と、飛びついてしまったのがダメだった。この方針(x以上のものを1, それ以外を-1として木DP)だと「答えがA[i]以上になるか?」という判定はできるが、(A[i]+A[j])/2となる場合の処理が上手くいかない(と思う、多分。)

 なので、考え方を変える。

 木の葉それぞれについて、「そこにたどりついたときの中央値」が求まれば、後は木DPで答えを求められる。
 で、実はこれはオイラーツアー(DFS順)みたいなことをしながらBIT上の二分探索をすることで求めることはできる。


 なお、$10^5$回くらいなら間に合うだろうとDFS部分を再帰で書いたら、PyPyだとTLEして、PythonでACできました。やっぱりPyPyの再帰は遅いなぁ。

H - Red and Blue Lamps

 解説AC。

 凸性を理解するため勉強しようと思って解説を見たのに、貪欲で解けるということでそれでACしてしまった。
 (貪欲解は)難しいけどなるほど、という感じ。

2021年9月9日木曜日

Educational Codeforces Round 113 (Rated for Div. 2)

 Dまで四完でした。


E. Playoff Restoration

 半分全列挙。
 半分全列挙は疑ったのに、半分に分けても混ぜることができない気がしてしまった。

 実際は、$\sum{ i \cdot A^{p_i}}$ がハッシュなので、各$A^{p_i}$ごとにindexの総和さえ分かればよく、それならぐっと数が減るので半分全列挙が機能します。

 ……と、納得してツイートしたらmaspyさんに不要だと指摘されました。(指摘ありがとうございます)

 Sample1で考えてみます。
 決勝で勝つか負けるかは考えずに半分全列挙をし、勝った場合負けた場合、それぞれについてハッシュ値を求めると、前半については、

・[5, 3, 5, 2]のときのハッシュ値
・[5, 3, 5, 1]のときのハッシュ値

 が分かっています。(こうやって列挙する数は$k=5$のとき、$2^15$個)

 この、[5, 3, 5, 2]に対応する後半のハッシュがあるかを調べるためには、

・h(問題文で与えられたハッシュ値)- [5, 3, 5, 2]のときのハッシュ値

 なるハッシュ値を取るものが後半の列挙した中で、かつ二位ではなく一位を使うものの中に存在すれば良いです。

 これ、ハッシュが和として定義されているから、半分のハッシュの和が分かれば残り半分は全体から引くことで求められる……と、当たり前なのだけれど、半分全列挙で上手くできるのはこの性質のおかげで、私が躓いたのはこの部分だったかと思う。

 そして、前半と同じように後半も列挙・調査しておけば、これが[1, 5, 5, 3]に対応しているということが分かります。

 シンプルな半分全列挙で、ナップザック問題の半分全列挙のように、ソートして二分探索(もしくは尺取り)というようなことも必要ない。

 半分全列挙というキーワードを思い付いたのなら、解けなくてはいけない問題でした。反省。

2021年9月4日土曜日

yukicoder contest 312

 Cまで三完でした。


No.1665 quotient replace

 Grundy数を求めてACしたが、素因数の個数を考えることでNIMに帰着できたのね。なるほど。

No.1666 累乗数

 解説AC。
 二つ目の方法でやりました。二乗の個数が他の累乗の個数より多いことには気付いていたのに、こういう方法に思いつかなかったのはまずい。

 約数包除での方法も理解しました。コンテスト中は、素数ベキに絞ってやることを考えていた。そこから約数包除は遠いような近いような。

No.1667 Forest

 解説AC。
 コンテスト中あまり考えなかったため解けなかったのは仕方ないけど、解説を見てすぐピンと来ないのは良くない。

・重複を除くため、残っている頂点のうち一番小さいものを何と組み合わせるかを考える
・ケイリーの公式

 この二つをちゃんと理解していれば解けたはずだし、どちらもそれほど特別な手法ではなかった。


2021年9月3日金曜日

CodeCraft-21 and Codeforces Round #711 (Div. 2)

  Eまで五完。時間ギリギリで通ったのは嬉しい!


F. Christmas Game

 解説AC。

 公式解説が分かりやすかった。
 こういう問題だとNIMに帰着するのは定石とはいえ、なかなか面白かった。

 が、解説では実装がよく分からず、全方位木DPだよね? と思ったらそう書いているツイートを見つけた。

 今回は逆元がある全方位木DPということで、実装はそれほど大変ではなかった。
 が、全方位木DPで得た配列の添え字のどこからどこまでを使うかで混乱、結局時間がかかってしまった。

 上手く書けたら全方位木DPのライブラリにしようと思って書き始めたのだけど、(まあまあ上手く書けた方かとは思うものの)結局遷移式とか添え字とかを考えるところが大変だからライブラリ化してもなぁ、という気持ちになったのでライブラリ化は見送りかなぁ。

 全方位木DPは二回DFSをやることになるわけだけど、一回目のDFSを書いたら二回目は書かなくていいようにライブラリ化したい。
 今回みたいに、DP配列の中身が配列の場合にも対応できるようにライブラリ化できるはずだよね。また今度やります。(先送りして良いのだろうか)

2021年9月2日木曜日

灘中入試コンテストday2

 Cまで三完でした。


No.1353 Limited Sequence

 解説AC。

 まず三つ目の条件を正しく理解することが重要。

・各i( 1 <=i<= N ) について、i が(A_i+1)個以上連続してはいけない

 という意味です。(コンテスト中はこれを解釈できずに飛ばしてしまった記憶が……)

 これさえ分かれば、

・同じ数字を付け加えるときは一気に付け加えれば良さそう

 と思えるので、それを利用してDPできます。
 問題を正しく理解できれば、そこまで難しくなかったか……。

No.1354 Sambo's Treasure

 fairly_lettuceさんの解説が分かりやすかった。
 考察が難しい問題ではないけど、包除原理のとき何を除けばいいかというあたりで混乱してしまった。順番が確定しているので、包除原理といっても$(-1)^N$をかけたりする必要がない、というのがポイントか。

 というわけで、理解したので実装してみようか、と思って書いたらかなり苦戦した。こういうのをさくっと実装できるようになるにあどうしたら良いのかなぁ。

No.1355 AND OR GAME

 解説AC。

 後ろから見るという発想はあったが、Pが分かっても、操作前のYが一意に決まらないためダメだと思ってしまった。分からないbitは分からないままにして計算すれば良かったのか。

2021年9月1日水曜日

AtCoder Beginner Contest 214

  Fまで六完でした。GとHは解法にかすりもしていなかった。要復習。


G - Three Permutations

 snukeさんの解説放送を見てAC。
 えー、難し過ぎませんか? ステップ数が多いし、一つ一つのステップが重い。今は理解できているけど、もう一度まっさらな状態から解けと言われると結構厳しい気がしてしまう……。

 以下、(提出コードにも書いたけおd)snukeさんの解説放送を聞いたメモ。
 
 順列→グラフの問題と考える。
 二つの順列から、サイクルの集合と考える。
 各辺について、両端の頂点以外のものを書き込むと考える。
 
 辺を、
・〇(両端以外を書き込むもの)
・×(両端のいずれかを書き込むもの)
・?(上記どちらでも良い)
 の三つに分ける。
 
 〇は扱いにくいので、包除原理を使う。
 
 2^N通りのうち、×の箇所を決め打つと、
 各連結成分について考えることで答えを求めることができる。
 
 ×の個数でDPする。
 DP[i][j] = iまで見て×がj個のときの場合の数 とする。
 
 各サイクルごとにDPする。
 辺を順々に見ていき、「直前の頂点を使ったか?」をflagに持つ。
 サイクルなので、最初の辺については二通り試す。

H - Collecting

 解説放送を聞いてAC。
 問題を見ても全くフローに思えなかったのでどうしようもないが、最小費用流と言われればなるほど、と思えた。Kが小さいのも、「フローを流す回数が小さい」と考えれば確かに、と。

 ただ、
・コストが負の辺があるので、それを解消する工夫が必要
・自分のフローライブラリが遅い

 ため、その後も非常に苦労した。
 一点目については、snukeさんの記事も理解しておきたいが、なかなか難しい……。

 二点目については、毎回距離を初期化して一からダイクストラしているのがまずい気がする。使い回せるところは使い回と高速化できそうな気がするが、よく分かっていない。