読者です 読者をやめる 読者になる 読者になる

土下座しながら探索中

主に競技プログラミング

SRM 596 Div1 easy

問題概要:
N個の要素をもつ配列が与えられる
その配列の各要素の初期値は0である
あなたは次の2つのオペレーションを行う事ができる
1. 配列の1つの要素を選び、その要素に1加える
2. 配列内の各要素を2倍する
N個の要素を含むもうひとつの配列が与えられたときに、最初の配列を与えられた配列と同じ状態にするために必要なオペレーションの最小回数をもとめよ

解法:
2進数になおす
0から最下位にビットを立てる動作とビットを1つ左にシフトする動作で入力と同じ状態にしろという事でした
例えば、 {2,1} という入力が与えられた時これらを2進数にすると

2 : 10
1 : 01

となります
これから分かるように立っているビットの数分は最低でも必要です
オペレーション2は配列内の要素をすべて1つ左にシフトすることを意味しています
つまり、必ず一番奥に立っているビットの場所分だけ2倍する必要があるのです

コード:

class IncrementAndDoubling {
public:
  int getMin(vector <int> array) 
  {
    int ans = 0,kcost = 0;
    rep(i,array.size())
      ans += __builtin_popcount(array[i]),kcost = max(kcost,(int)log2(array[i]));
    return ans + kcost;
  }
};