Tenka1 Programmer Contest (2017) D - IntegerotS
問題
提出コード
(こちらは手直しを加えたコードになります、最初に通したコードはこちらです)
手直しを加えた理由が、当初がなぜかlong long型に収まらないと勘違いしていたため、unsigned long long型で計算をしているため、いろいろ複雑になってしまっているためです。それ以外にも、さらに考察を詰めて簡潔にしています。
解法
を2進数に直した時の、最上位の桁から順番に見ていきます。
として考えてみます。
まずは、論理和がとなるように整数を購入してみます。これが答えの候補の1つになります。最上位以外のビットが立っていない部分が存在しても問題ありません(例えばの例の場合、となるようなパターンです)。これは、とのORをとったときにと一致するようなについてのの総和になります。
続いて、他の答えの候補を探します。ありうるパターンとして、最上位のビットを使用するかどうか、という2つのパターンが存在します。それぞれのパターンでの最大値を求め、最初のものと合わせて一番大きいものが答えになります。
最上位のビットを使用しないパターン
このパターンでは、最上位ビットを使用していないはすべて買うことができます。
右から桁目が最上位ビットだとすると、そのビットが表す数字はになります。
このとき、論理和がとなるように購入することができます。これは、最上位ビット以外がすべて立っている状態を表しています。 の例だと、になるようなパターンです。また、最上位ビット以外が立っていない部分が存在しても(例えば )、必ずを下回っているため、とにかく最上位ビットが立っていない整数を全て買ってしまうのが一番価値が高くなります。これは、を満たすの総和になります。最上位のビットを使用するパターン
最上位のビットを使用すると考えたとき、全てのについて、最上位ビットは0であろうが1であろうが関係がなくなります。これらが購入することができるかどうかは、最上位ビット以外の決め方が関係します。
ということで、
およびについて、最上位ビットを無視した場合の最大値が答えになります。
をあたらしくと定義しなおせば、規模を縮小した問題に帰着できます(についても、の減算をし忘れないようにします。を満たすものについてのみ行います)。
あとは、が1桁(1か0)になるまでと、および答えの更新を続け、最終的な最大値を求めれば答えとなります。