Codeforces Global Round 4

反省会場

 

codeforces.com

 

 

A - Prime Minister

問題:

1.過半数の席が欲しい

2.連立政権ができるが、Aliceの政党の半分以下の議席の党だけしかできない。

3.連立する党の数を最小化したということがわかる

 

 

考察:

・Aliceの議席の半分以下の政党をまとめてソート。大きい順にいれて、全体の半分を超えたところが答え。

・最後まで超えないときはNO

 

 


B - WOW Factor

問題:Wを連続するV2つで代用してWOWを作りたい。VとOの文字列が与えられる。連続するVVをWとして使うことで、連続しなくてもよい部分文字列WOWがいくつ作れるか。

 

 

考察:

・典型

・Oを固定してそれぞれのOで考える。

・左右のVVの数の積が、そのOを使うときの場合の数
・累積和でOK

・長さが10^6なのでLLじゃないとオーバーフローする…。これに気づかず2時間頭抱えてました(やばすぎ)

 

 

 


C - Tiles

問題:W*Hにななめに黒白にわかれたタイルを置く。黒も、白も隣接しないような置き方はいくつあるか

 

 

 

考察:

・左上を決めるとその横は2通り、その下も2通り。

・その右下は1つに決まる

・左上は4通りなので、4*2^(h-1)*2^(w-1)=2^(w+h)

 

黒だけ隣接してはいけないと誤読してて2時間頭抱えてました(ちゃんと読もう)

 

 


D - Prime Graph

問題:以下の条件を満たすN頂点の連結単純グラフを求めよ

1.辺の数Mが素数

2.各頂点の次数が素数

 

 

考察:

・貪欲に考えると、最小の素数で構成できるかを考える

・まず連結なので、N-1本以上は枝が必要である。

・また各頂点の次数が素数なので、2以上。端点が2N個なので枝はN以上必要

 

・そうするとN以上の最小の素数で構成できるかを考えればよい。

・難しいのでグラフのほうを考える。

・二重辺にならないように辺を増やす。次数が2から3、5と増やす。

・3までで、N/2個増やせる。

・神様が1000までのNはN以上1.5*N以下に素数が存在することを教えてくれる。調べるとあってる。

・次数2か3で良いことがわかれば簡単。

素数判定はN*sqrt(N)でよいので間に合う

 

 

 

これ爆速で通したの良かった。

 

 

 

 


E - Archaeology

問題:a,b,cで構成された文字列Sが与えられる。長さS/2以上の対称な(連続でなくてもよい)部分文字列を求めよ

 

実は、隣り合う文字が違うことが保証されてる

 

考察:

・先頭と最後尾を2文字ずつ見ると、必ず一致する文字がある。

・なぜならab…cdとするa!=b、c!=dは保証されている。もしa!=c、a!=dなら、3種類出てるので、bがc、dのどちらかと一致する。

 

・同じ文字を取っていって長さ半分くらい+1文字出力するとうまくいく

 

 

隅々まで問題を読もうね…

 

 

 

 


F1 - Short Colorful Strip

問題:N個のマス目をN色で塗る。塗る色が指定される。各色1マス。以下のルールで塗って、与えられる列と一致させたい。何通りあるか。

・色1から順番に塗る。

・重ね塗りするときは、はみ出してはいけない。

 

 

考察:全く分からん

 

 

解説:

・ある範囲の塗り方DP[l][r]通りとする

・ある色で塗られた範囲[l,r]を考える

・次に塗るのはその中で最小の色c、場所kである。

・色cを塗る範囲を[a,b]とすると、a,bの全通りに対して

DP[l][r]=sum(DP[l][a-1]*DP[a][k-1]*DP[k+1][b]*DP[b+1][r]

という遷移になる。l、r、a。bで調べるので配列N^2、遷移N^2のO(N^4)である

・工夫するとO(N^3)にできる←これはなに

 

 

コード見ればわかるかもしれないけど放置中

DPっぽさあったけどわからなかった。範囲DPは計算ドリル感あるし解きたかった

 

 

 

※ベンツヨしたんで追記します

 

まず解説を読み解くとこから

 

1.DP[l][r]:ある範囲が1色で塗られているとき、その範囲だけを考えたときの塗り方の場合の数

 

[l,r)の範囲がなにかしらの色(無色でもよい)で塗られているとします。

このときl-1やrは、別の色の必要があります。また、その色を示すマスが含まれないとします。

 

このあと、その範囲はどの色で塗られるでしょうか。

 

 

 

ちょっとわかりづらいのでSample2の例で考えてみましょう。

4 5 1 6 2 3 7

というマスがあります。

 

はじめに4,5,1,6,2を色1で塗るとしましょう

4 5 1 6 2 3 7

ここでDPを考慮する場所は

4 5    6 2  と 3 7

の3つの区間です。[0,2) と [3,5)、[5,7)です。

 

 

左側を塗る通りはDP[0][2]です

右側を塗る通りはDP[3][5]*DP[5][7]です。これは別の色で塗られている区間は独立だからです。

4から2までを色1で塗った時の場合の数はDP[0][2]*(DP[3][5]*DP[5][7])で求まることがわかりました。

 

色1で塗る方法は左側の境目が0,1,2,3で、右側の境目が4,5,6,7です。

この全てで計算して足せば色1の塗り方が求まります。

 

 

 

次に、ある区間で次に調べる色を考えます。

例えば区間[0,2)であれば、4 5なので、小さい方4で塗ることになります。

つまり、区間の最小値を求めればよいです。自分は雑にセグ木を使いました。もっと手軽な方法があるかもしれません。

 

 

 

 

 

まとめます

・最後にDP[0][n]を求めたい

 

・DP[l][r]を求めるには

1.[l,r)の最小値cと場所kを求める

2.[l,a)、[a,k)、[k+1,b)、[b,r)をあり得るa,b全てで調べる

ここでa,bは独立に考えてよいです。なので

DP[l][r]=ΣΣ( DP[l][a-1]*DP[a][k] * DP[k+1][b]*DP[b+1][r] )

           =Σ( DP[l][a]*DP[a][k] ) * Σ( DP[k+1][b]*DP[b][r] )

となりO(N)での計算が可能です。

 

・DP配列は、lとrでN^2個なので遷移がO(N)より、全体でO(N^3)で求めることができます。

 

 

 

・実装についてですが、再帰で大丈夫でした。再帰にしないなら区間が短い順、左側からとかで求めていく感じだと思います。なんかバグりそう

 

 

 

 

 

 

 

 

感想

誤読というか問題文読めてないの多すぎる

 

とりあえずLL使っておいたほうがいいですね

 

ABCあとで疲れていたのもあったのでまあ仕方ないかなと思います

 

もうちょっとで水色落ちしちゃうので、明日のエデュフォは頑張りたいなー。

まあ水に落ちたらDiv3に出れるというメリットがある(?)