C-merのブログ

ザ・雑記

SRM 519 Div 1 - Problem 250 BinaryCards

問題
SRM 519 Div 1 - Problem 250 BinaryCards
TopCoder Statistics - Problem Statement

使用言語
C++

問題概要
0から63までの数字のカード(全て1枚ずつ)を使う.数字xのカードには2ˆxのドットが描かれている.
最初全てのカードは伏せられている.AからBまでの連続する整数について,カードを表にして,カードに描かれるドットの数で表す.表になったカードのドットの合計を求める.

方針
表のカード(のドットの数)について考えると,
 6: 2 4
 7: 1 2 4
 8: 8
となる.表になったドットは 1+2+4+8=15
→各数字のビット和でわかりそう

しかし,O(N)で最大10ˆ18になるので連続する整数のビット和を全て取るのは現実的でない.

ここで単純化して考える.
A = 2ˆ30 + 1, B = 2ˆ30 + 24とする.
答え(Cとする)にはもちろんA, Bが含まれる(C|A==A, C|B==B)
差分について考えると,23 = 16 + 4 + 2 + 1 = 0x10111
これの最上位ビット以下のは全て1になりそう(例 20ˆ3+8)
なのでそれ以下を1にする.

所感
・わかりにくすぎる問題文に反して,楽しい問題
・コード短すぎ問題

コード

class BinaryCards {
    public:
    long long largestNumber(long long A, long long B) {
      ll ans = A | B;
      //差分の最上位ビット以下のビットが1になるようにOR
      //どうせ最上位以下のビットは全て1になるので,最上位1つずつ左シフトしてforループ
      for (ll i = B - A; i > 0; i = i>>1) ans |= i;
      return ans;
    }
};