C++で指定された数値のセットビットから作れる最小の数を求める方法
問題の概要
符号なし整数が与えられたとき、その数値に含まれる「セットビット(1になっているビット)」だけを使って構成できる最小の数を求めます。
例
入力が 10 の場合、答えは 3 になります。
10 の2進表現は 1010 であり、セットビットは2つあります。2つのセットビットを持つ最小の数は 0011、すなわち 3 です。
アルゴリズム
- 与えられた数値のセットビットの個数を数えます。
- 2^(セットビット数) − 1 を計算した値が、求める最小の数になります。
たとえばセットビットが3個の場合は 2^3 − 1 = 7(2進数で 111)となります。セットビットをすべて下位の桁に集めた形が最も小さい数になるためです。
C++での実装例
#include <bits/stdc++.h>
using namespace std;
// セットビットの個数を数える関数
int getSetBits(int n) {
int cnt = 0;
while (n) {
++cnt;
n = n & (n - 1); // 最下位のセットビットを消していく
}
return cnt;
}
// セットビットから作れる最小の数を返す関数
int getMinNumber(int n) {
int bits = getSetBits(n);
return pow(2, bits) - 1;
}
int main() {
int n = 10;
cout << "Minimum number = " << getMinNumber(n) << endl;
return 0;
}
上記のプログラムでは、n & (n - 1) というビット演算のテクニックを使うことで、ループごとに最下位のセットビットを1つずつ消去し、効率よくセットビット数をカウントしています。
このプログラムをコンパイルして実行すると、次のような出力が得られます。
出力結果
Minimum number = 3
-
C++でL番目からR番目のインデックス間のみビットがセットされた数を求める方法
問題の概要 この問題では、指定された範囲LからRの間にあるすべてのビットがセット(1)になっている数の値を求めます。具体的な例を見てみましょう。 入力: L = 1, R = 5 出力: 62 説明: LとRを2進数で表すと 0..0111110 となります 入力: L = 1, R = 4 出力: 30 説明: LとRを2進数で表すと 0..11110 となります 解法へのアプローチ この問題に対して、シンプルな全探索(ブルートフォース)と、ビット演算を活用した効率的なアプローチの2つの方法を紹介します。 方法1: 全探索(ブルートフォース) このアプローチでは、指定された範囲を順番に走査
-
C++で集合の反射関係の数を求める方法
この記事では、C++を使って集合上に定義できる反射関係(reflexive relation)の総数を求める方法について解説します。問題設定としては、整数 n が与えられたとき、n 個の自然数からなる集合上に存在する反射関係の個数を求めるというものです。 反射関係とは 集合 A 上の関係 R が反射的であるとは、「A に属するすべての要素 a に対して、順序対 (a, a) が必ず R に含まれる」という条件を満たすことを意味します。数式で表すと次のようになります。 (a, a) ∈ R (∀ a ∈ A) 具体的な入出力の例を見てみましょう。 入力 : x = 1 出力 : 1 説明 : 集