Codeforces Round #550 (Div. 3)E. Median String
問題概要
二種類の文字列 について, 辞書順でちょうど の真ん中な文字列を求めよ.
制約
- と の間にある文字列は奇数個
解法
文字列を 進数の数とみれば, を出力するだけです. ただし, 桁の数を扱うのは無理があるので, 上手に計算する必要があります.
とはいっても, 普通に筆算のように計算するだけです. を表す数列をつくり, 上の桁から で割っていきます. 余ったとき, 下の桁に繰り下がるのは ではなく のことだけ気を付けましょう.
実装
Codeforces Round #531 (Div. 3)F. Elongated Matrix
問題概要
の行列が与えられる. この行列について, 行を自由に入れ替える. この結果できた行列を としたとき, 数列 を として定める.
このとき, ある に対して, 全ての について が成り立つとき, は良い数列であるという.
与えられた行列に対し, 良い数列が存在する最大の を求めよ.
制約
解法
見るからに二分探索です. 解となる を決め打ちして, 良い数列が構築できるか判定しましょう.
番目の行の次に 番目の行が来れるかどうかは, ならば来れると判定できます. これは, 各行を頂点とし, 条件を満たすとき の辺を張ることにすれば, 全ての頂点をめぐって最初の頂点に帰ってこれるか?という判定問題に帰着することができます.
そこで, 始点を全探索し, TSP のように bitDP をすれば, あらかじめグラフを構築しておけば で良い数列を作れるかどうかを判定できます.
この上で二分探索の分の が乗ってくるので計算時間的には怪しいですが, C++ を信じて投げましょう.
実装
Codeforces Round #529 (Div. 3)F. Make It Connected
問題概要
頂点のグラフ が与えられる. 番目の頂点には数字 が割り当てられており, 最初は辺が張られていない. このとき, に対して辺を張ることによって, 全域木を作成したい. このとき, 頂点 と 頂点 を結ぶのにはコスト がかかる.
ただし, 個の辺があたえられ, 番目の辺は と を指定する. この辺については, の代わりにコスト で結ぶこともできる( で結んでもよい).
全域木を作るのに必要な最小コストはいくらか?
制約
解法
辺を張れる候補は だけあるため, そのまま MST をすると当然 TLE します. どのようにすればよいでしょうか?
よくある発想として, 必要な辺だけ候補に入れることで辺の本数を減らすことを考えます. たとえば, だとすれば, が最小の頂点を として, を中心としたウニグラフを構築するのが明らかに最小になります.
よって, この辺が追加されたとしても, MST を構築しうる辺は 個の辺たちと とつながっている辺のみです(これ以外の辺を用いることによってコストが下がることはありません). よって, これらの辺をまとめてソートしクラスカル法などで MST を構築すればいいです. このとき辺の本数は 程度なので, 問題なく間に合います.
実装
Codeforces Round #506 (Div. 3)F. Multicolored Markers
問題概要
の赤い正方形が 個, 青い正方形が 個与えられる. 個の正方形を敷き詰めることにより長方形を作るが, このとき少なくとも赤か青の一方の正方形だけでも長方形が完成されているようにしたい. このような敷き詰め方のうち, 周の長さが最小値はいくらか?
制約
解法
まず, 個の正方形を敷き詰めてできる長方形を全探索しましょう. これは の約数を列挙すればよく, これは で行えます.
この上で, 完成される長方形に対して赤もしくは青で内部に長方形を作れるかを判定します. これは 及び の約数列挙を行うことにより判定をすることができます.
たとえば, のような形で表せるとき, 長方形の短辺, 長辺をそれぞれ とすれば かつ ならば条件を満たせると判断できます. この判定は実行時間制限に間に合うでしょうか?
じつは, 制約上限のような 程度の数に対しては, 約数は最大でもたかだか 程度しかありません. ですから, 全ての約数に対して条件を満たせるか判定しても 程度の計算回数で判定することができるので, 間に合わせることができます.
実装
Codeforces Round #490 (Div. 3)F. Cards and Joy
問題概要
長さ の数列があり, 番目の要素は である.
この数字を 人に 個ずつ配る. 番目の人は数字 を好んでおり, 配られた数字の中の の個数が ならば幸福度 を得る.
自由に数列を配れるとき, 全体の幸福度の最大値はいくらか?
制約
解法
数字 を好む人に, あるだけ を配るのが最適なのはすぐわかります. では, 数字 を好む人が 人いて, 数字 が 個あるとき, 得られる最大値はいくらでしょうか?
一人 枚までしか配ることができないので, のとき明らかに幸福度の最大は です( 人全員に を 個ずつ配ることができます). これを満たさない場合を考えましょう.
( 人に 個の数字を配るときの幸福度の最大値) としましょう. 遷移を考えれば, 人目に 数字を 個配る場合それぞれについて考えれば良いですから,
となります. この dp テーブルは で埋められることがわかります.
これさえできれば, 各数字の個数とそれを欲している人数を std::map などで管理すれば, 答えを求めることができます.
実装
Codeforces Round #490 (Div. 3)E. Reachability from the Capital
問題概要
頂点数 の有効グラフが与えられる. 頂点 からすべての頂点に到達可能にするには最小であと何本有向辺を追加すればよいか?
制約
解法
強連結成分分解をしたうえでトポロジカルソートをすれば, どの頂点に優先して辺を張ればいいかがわかります(よりトポロジカルソートしたときに早い頂点に辺を張りたいはずです).
ただし, から到達さえできればいいので, 次のようにすればいいです.
- 到達可能かどうかを表す bool 配列 を用意する. はじめ で初期化する.
- から到達可能な頂点 について, bfs などで としておく.
- 頂点集合をトポロジカルソートし, 頂点番号の早い順にみていく. もし なら辺を張る必要がないのでスルーし, なら辺を張ることにして答えに を加算し, また から到達可能な頂点 をすべて に変更する.
- 答えを出力する.
このアルゴリズムではたかだか定数回しか各頂点を見ないので, 時間計算量 で答えを得ることができます.
実装
ACL の scc を用いると非常に実装が簡便です.
Codeforces Round #527 (Div. 3)F. Tree with Maximum Cost
問題概要
頂点の木が与えられる. 頂点 には値 が割り当てられている. 頂点 に対し関数 を
と定義する. を自由に選べるとき, の最大値はいくらか?
制約
解法
典型的な全方位木dpの問題です. 全方位木dpがわからない方はまずググってください.
最初に部分木についての問題を解きましょう. これは普通に木dpをすればいいです. (頂点 の部分木についての の値), (頂点 の部分木にある頂点についての の総和) という風に定義すれば, 頂点 についてその の値は, 全ての の子頂点 について を足しあげた値になります. これは, 子頂点の に加え, 間の辺を通ることによって加算される量が に等しいことを利用しています(実験してみてください).
ここまでできればあとは全方位木dpするだけです. を頂点 の最終的な答えだとすれば, その子頂点 の答えは
です( は の総和です). 自分の部分木の答え(第 項)に加え, 自分の親頂点の答え(第 項)から自分の部分木の影響(第 項)を除いた後, 親頂点を自分の部分木としてマージする係数(第 項)がついてこの式になります.
あとは適当に dfs すればおしまいです.
実装
Submission #146591764 - Codeforces