Codeforces Round #558 (Div. 2)
ばたや
A. Eating Soup
問題:n人が円状にならんでいるとき、m人を退席させる。非連続にわかれる最大の個数を求めよ
考察:
n/2までは増えてそれからは減りそうです。
奇数のときでn/2付近が怪しいので実験して丁寧に解きましょう
B1. Cat Party (Easy Edition)
B2. Cat Party (Hard Edition)
問題:n個の整数列がある。k個目までで、1要素削除したとき、出現する数字のそれぞれの出現回数が等しくなるようにしたい。最大のkを求めよ
考察:
1要素削除して回数が一致する場合を考えます。
まず出現回数の種類は2種類以下の必要があります。
はじめに2種類のときです。多いほうの出現回数の出現回数が1回で、差が1のときOKです。また、1回の出現回数が1回のときもOKです。
わけわからないので具体例を出します。以下はそれぞれの整数の出現回数を列挙したものです
1-1:3,3,3,4
1-2:1.3,3,3
こんな感じです。
次に1種類のときです。
出現回数の出現回数が1回か、出現回数が1のときOKです
具体例です
2-1:4
2-2:1,1,1,1,1,1
出現回数のmapと、出現回数の出現回数のmapを持てばO(NlogN)で実行可能です。
実装にすごい苦労して1時間くらいかかっちゃいました。
下手すぎる
こういう愚直に場合分けするのはIQが試されてる感じがして苦手です。なぜならIQ低いので。
C1. Power Transmission (Easy Edition)
C2. Power Transmission (Hard Edition)
問題:n個の点がある。任意の頂点対を取り、2つを通る直線を引く。直線の交差する数を求めよ
考察:
直線の傾きと切片をすべて出します。
どちらも一致するものを削除します。
もし傾きが同じなら交わらないです。
傾きが違うもの*傾きが同じもの
これをすべての傾きで行えばよいです。
O(N^2logN)程度で実行可能です。
実装:
long doubleでやると破滅します。しました。
直線を表すとき、xの増加量:yの増加量で判別すればよいです。
それぞれをa,bとかおきます。式をガチャガチャすると切片cで表せます。
比を取る際にgcdで割ったり-1をかけたりします。
gcdの関数に0であるときの注意をしておきましょう。すべての点はdistinctなのですべて0になることはないです。
2点を通る直線を表す
ax-by=c
a=y1-y2
b=x1-x2
c=x2y1-x1y2
これを毎日3回、ロシアの方角に向かって唱えることにしました。
D. Mysterious Code
問題:文字列cの*を好きな文字に置き換えたとき、連続する部分列が、文字列sに一致する数-文字列tに一致する数の最大値を求めよ
解説:
KMP法を使うらしいです。
KMP法:
KMP配列を前計算し、文字列の中に出現するパターン文字列を求めるアルゴリズムです。
KMP配列とは、パタンのk文字目がパタンの接頭辞と一致するかの判別を示します。
あるk文字目が一致しないとき、また1文字目から確かめるとO(NM)になってしまいます。したがってどこまで戻ればいいかを記録します。
一致するなら1つ進み、一致しないなら一致するまで戻って1つ進みます。
もしk文字目がcのとき、どのような遷移をするかをすべて求めます。
与えられた文字列を見ながらその遷移を行ったとき、パタンの最後まで見れれば一致しているといえます。
これを*がどの文字になるかで遷移を計算します。
パタンsとtそれぞれの何文字目を見ているか、与えられた文字列分があり、遷移は前計算をすることでO(1)です
したがってO(|c||s||t|)で解くことができます。
なんとなーくKMP法についてわかったようなわかってないような。
コードを空で書いたり応用することは不可能な段階なので、しっかり復習したいと思います。