水銀メモ_________φ

外部記憶装置として再開

CodeForces #375_Div2 : C. Polycarp at the Radio

Problem - C - Codeforces

問題

大きさ  n の整数配列  a が与えられる。
 a_iの値を任意の値に変更することができる」 という条件下で、
1からm  ( m \leqq n) それぞれの値の出現数の最小値を最大化させたい。

最大化させた出現数の最小値 / この時の最小変更回数 / 変更後の配列 を求めよ。

解法

まず第一に配列の大きさ n 、最大化させたい値の範囲 mから 、
最大化させた出現数は  \lfloor\frac{n}{m}\rfloor に固定される。 ( M =  \lfloor\frac{n}{m}\rfloor とおく)

( m を超える値の数の総数) + (1からm の中で出現数がMを超えた差分) を使って
1m の内、出現数がMに達していないものを補填してあげれば良い。

1m の出現数を配列  c
( m を超える値の数の総数) を  f[m]、
(1からm の中で出現数がMを超えた差分) を  f[0]〜f[m-1] に入れ管理している。

計算量は O(n+m)

ソース

感想

やるだけの問題なのに落としたのが勿体なさすぎる・・

TopCoder SRM689_Div2 : ColorfulGardenHard

TopCoder Statistics - Problem Statement

問題

花の種類を表す文字列ある位置における配置禁止の色 の二つの情報が与えられる。
花は色を持ちアルファベットで表現される。

与えられた花を以下の条件に従い並び替えた時、 そのパターンの総数を求めよ。 (重複は除く)
同じ色の花が隣合わない
位置iで禁止されている色を置いてはいけない

解放

文字列の長さが高々15のため、bitDPを利用できる。(制約からすぐに気付きたい)
重複を避けるために各bitマスクの状態で、次に追加する特定の色が2回以上選択されないように注意する。

計算量は  O(2^n n^2) となる。
bitマスクの状態数  2^n 通り
最後に選択した色  n 通り
各状態に対して、最大 n 通りの次に選ぶ花の選択技

コード

gist.github.com

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

問題

1kまでナンバリングされたボールがそれぞれc_i個与えらえる。
これらのボールを全て並べたとき、color(i)の中で右端に存在するボールよりも右側に
color(1)〜color(i-1)が存在しないような並べ方が何通りあるか求めよ。

解法

ナンバーの小さい順にボールを配置していく。
color(i)を配置する際、最も右側に存在するcolor(i)よりも右側にcolor(1)〜color(i-1)
存在してはいけないので、まずcolor(i)のうち1つを右端に配置する。
残りのc_i -1個のボールを、既に配置されているボールの隙間に重複を許して配置すれば良い。
例えば以下の例で、c_3=3を追加したい場合  _5H_2を計算する。 f:id:suigingin:20160404011004p:plain

重複組み合わせについては hosさんのスライド が分かりやすいと思う。
ボールの総数が1000を超えないためコンビネーションの計算にパスカルの三角形を使用できる。

コード

CodeForces #8VCVentureCup : D. Jerry's Protest

Problem - D - Codeforces

問題

ツボの中に重複のない番号の書かれたボールがn個入っている。
Andrew Jerryはこのツボの中から同時にボールを一つだけ無作為に選びとり、
番号の大きい方が勝者となる。(選んだボールはツボにまた戻す)

このゲームを3回連続で行った時、
最初の2回は Andrewが勝ち最後の1回は Jerryが勝ったとする。
3回のゲームを通して Jerryの出た番号の和が Andrewより大きくなる確率を求めよ。

解法

dcを以下のように定義し
勝者が敗者にi枚差・i以上差をつけて勝つパターン数を事前に求める。
cdの累積和から得ることができる。

  • d[i] := 1回の勝負で勝者が敗者にi枚差をつけて勝つパターン数
  • c[i] := 1回の勝負で勝者が敗者にi枚以上差をつけて勝つパターン数

d,cより以下の場合の数を、差の最大値(5000)の2重ループで求める。
1戦目. Andrewi枚差をつけてJerryに勝った
2戦目. Andrewj枚差をつけてJerryに勝った
3戦目. Jerryi+j+1枚以上差をつけてAndrewに勝った
d[i] * d[j] * c[i+j+1]

最後に、条件を満たすパターンの総数を、全パターン {(\frac{n*(n-1)}{2})}^3 で割ればよい。

全体の計算量は O(n^2 + a_{max}^2)となる。

ソース

CodeForces #276_Div2 : C. Bits

Problem - C - Codeforces

問題

n回クエリが投げられる。(各クエリはLRからなる)
LR間の整数で、bitの立っている数が最大となるような最小の値を求めよ。

解法

Rの上限が10^{18}と大きいため、LからRへ値を1ずつ増やしながら
範囲内全ての値のbitをカウントする方法では間に合わない。

Lをベースになるべく値が増えないようにbitを立てたいので、Lの右端から順にbitを立てていけばよい。
計算量は O(nlogR)となる。

コード

CodeForces #256_Div2 : D. Multiplication Table

http://codeforces.com/contest/448/problem/D

問題

n * mの二次元テーブルが与えられる。
ij列目の値はi * jと定義される。
このテーブルの内、k番目に大きい要素を答えよ。

例えば、n=2, m=3の場合テーブルは以下の図のようになり、
k=4 の時、その答えは3となる。
f:id:suigingin:20160207055557p:plain

解法

n,mの最大値が 5·10^5と大きいため、
テーブルを愚直に構築し全探索を行うことはできない。

「ある数xk番目に大きい」というのは以下のように言い換えられる

  • テーブル内にx以下の数はk個以上存在する
  • テーブル内にx未満の数はk個未満存在する

つまりk番目に大きい数は、ある数x以下の数がk個以上存在するような
最小のxを探せば良いことが分かる。
これはテーブル上にx以下の個数がいくつ存在するか調べる事ができれば、
二分探索で効率よく求めることができる。

では、テーブル上でどのようにx以下の個数を数える事ができるか。
これは行・列がそれぞれ単調増加している性質を利用してテーブルをジグザグ
移動しながら求めることができる。

例として4 * 5のテーブルで8以下の個数を数えたい場合、
以下のようにポインタを動かしその数は13個となる。

  • 今いるマスの値が8以下
    • そのマスの左側は全て8以下であることが分かるため その幅の分だけ加算し次の行へ
  • 今いるマスの値が8を超える
    • 8以下になるまで左側に寄せる
      f:id:suigingin:20160207155928p:plain

ジグザクする回数は高々(n+m)回のため、全体の計算量は O((n+m)lognm)となる。

コード