CodeForces #375_Div2 : C. Polycarp at the Radio
問題
大きさ の整数配列 が与えられる。
「の値を任意の値に変更することができる」 という条件下で、
から それぞれの値の出現数の最小値を最大化させたい。
最大化させた出現数の最小値 / この時の最小変更回数 / 変更後の配列 を求めよ。
解法
まず第一に配列の大きさ 、最大化させたい値の範囲 から 、
最大化させた出現数は に固定される。 ( とおく)
( を超える値の数の総数) + (から の中で出現数がを超えた差分) を使って
〜 の内、出現数がに達していないものを補填してあげれば良い。
〜 の出現数を配列 、
( を超える値の数の総数) を ]、
(から の中で出現数がを超えた差分) を ]〜] に入れ管理している。
計算量は
ソース
感想
やるだけの問題なのに落としたのが勿体なさすぎる・・
TopCoder SRM689_Div2 : ColorfulGardenHard
TopCoder Statistics - Problem Statement
問題
花の種類を表す文字列 と ある位置における配置禁止の色 の二つの情報が与えられる。
花は色を持ちアルファベットで表現される。
与えられた花を以下の条件に従い並び替えた時、 そのパターンの総数を求めよ。 (重複は除く)
・ 同じ色の花が隣合わない
・ 位置iで禁止されている色を置いてはいけない
解放
文字列の長さが高々15のため、bitDPを利用できる。(制約からすぐに気付きたい)
重複を避けるために各bitマスクの状態で、次に追加する特定の色が2回以上選択されないように注意する。
計算量は となる。
・ bitマスクの状態数 通り
・ 最後に選択した色 通り
・ 各状態に対して、最大 通りの次に選ぶ花の選択技
コード
ARC #050:B. 花束
問題
B: 花束 - AtCoder Regular Contest 050 | AtCoder
解法
片方の色の花束をいくつ作るか決めた時に、作ることのできる花束の総数が凸関数になる。
よって片方の色の花をいくつ作るかについて三分探索をすればよい。
三分探索については以下の記事が参考になります。
・ 三分探索と黄金分割探索 - naoya_t@hatenablog
解説では二分探索による解法が紹介されています。
(こちらは理解できていない・・)
ソース
CodeForces #309_Div1 : A. Kyoya and Colored Balls
http://codeforces.com/contest/553/problem/A
問題
1〜kまでナンバリングされたボールがそれぞれ個与えらえる。
これらのボールを全て並べたとき、color(i)の中で右端に存在するボールよりも右側に
color(1)〜color(i-1)が存在しないような並べ方が何通りあるか求めよ。
解法
ナンバーの小さい順にボールを配置していく。
color(i)を配置する際、最も右側に存在するcolor(i)よりも右側にcolor(1)〜color(i-1)が
存在してはいけないので、まずcolor(i)のうち1つを右端に配置する。
残りの個のボールを、既に配置されているボールの隙間に重複を許して配置すれば良い。
例えば以下の例で、を追加したい場合 を計算する。
重複組み合わせについては hosさんのスライド が分かりやすいと思う。
ボールの総数が1000を超えないためコンビネーションの計算にパスカルの三角形を使用できる。
コード
CodeForces #8VCVentureCup : D. Jerry's Protest
問題
ツボの中に重複のない番号の書かれたボールがn個入っている。
Andrewと Jerryはこのツボの中から同時にボールを一つだけ無作為に選びとり、
番号の大きい方が勝者となる。(選んだボールはツボにまた戻す)
このゲームを3回連続で行った時、
最初の2回は Andrewが勝ち最後の1回は Jerryが勝ったとする。
3回のゲームを通して Jerryの出た番号の和が Andrewより大きくなる確率を求めよ。
解法
d、cを以下のように定義し
勝者が敗者にi枚差・i枚以上差をつけて勝つパターン数を事前に求める。
cはdの累積和から得ることができる。
d[i] := 1回の勝負で勝者が敗者にi枚差をつけて勝つパターン数
c[i] := 1回の勝負で勝者が敗者にi枚以上差をつけて勝つパターン数
d,cより以下の場合の数を、差の最大値(5000)の2重ループで求める。
1戦目. Andrewがi枚差をつけてJerryに勝った
2戦目. Andrewがj枚差をつけてJerryに勝った
3戦目. Jerryがi+j+1枚以上差をつけてAndrewに勝った
d[i] * d[j] * c[i+j+1]
最後に、条件を満たすパターンの総数を、全パターン で割ればよい。
全体の計算量はとなる。
ソース
CodeForces #276_Div2 : C. Bits
問題
n回クエリが投げられる。(各クエリはLとRからなる)
L〜R間の整数で、bitの立っている数が最大となるような最小の値を求めよ。
解法
Rの上限がと大きいため、LからRへ値を1ずつ増やしながら
範囲内全ての値のbitをカウントする方法では間に合わない。
Lをベースになるべく値が増えないようにbitを立てたいので、Lの右端から順にbitを立てていけばよい。
計算量はとなる。
コード
CodeForces #256_Div2 : D. Multiplication Table
http://codeforces.com/contest/448/problem/D
問題
n * mの二次元テーブルが与えられる。
i行j列目の値はi * jと定義される。
このテーブルの内、k番目に大きい要素を答えよ。
例えば、n=2, m=3の場合テーブルは以下の図のようになり、
k=4 の時、その答えは3となる。
解法
n,mの最大値がと大きいため、
テーブルを愚直に構築し全探索を行うことはできない。
「ある数xがk番目に大きい」というのは以下のように言い換えられる
- テーブル内にx以下の数はk個以上存在する
- テーブル内にx未満の数はk個未満存在する
つまりk番目に大きい数は、ある数x以下の数がk個以上存在するような
最小のxを探せば良いことが分かる。
これはテーブル上にx以下の個数がいくつ存在するか調べる事ができれば、
二分探索で効率よく求めることができる。
では、テーブル上でどのようにx以下の個数を数える事ができるか。
これは行・列がそれぞれ単調増加している性質を利用してテーブルをジグザグ
移動しながら求めることができる。
例として4 * 5のテーブルで8以下の個数を数えたい場合、
以下のようにポインタを動かしその数は13個となる。
- 今いるマスの値が8以下
- そのマスの左側は全て8以下であることが分かるため その幅の分だけ加算し次の行へ
- 今いるマスの値が8を超える
- 8以下になるまで左側に寄せる
- 8以下になるまで左側に寄せる
ジグザクする回数は高々(n+m)回のため、全体の計算量はとなる。