C++
 Computer >> コンピューター >  >> プログラミング >> C++

【C++】セットビット数が素数となる数を範囲内で数える方法

この記事では、2つの整数 L と R が与えられたとき、L から R の範囲内にある整数のうち、セットビット(2進表現で1になっているビット)の数が素数であるものの総数を求める方法を解説します。

問題の概要

まず、具体的な例で問題を確認しましょう。

入力: L = 7, R = 12
出力: 6
説明:
7  → 111、セットビット数 = 2(素数)
8  → 1000、セットビット数 = 1(素数ではない)
9  → 1001、セットビット数 = 2(素数)
10 → 1010、セットビット数 = 2(素数)
11 → 1011、セットビット数 = 3(素数)
12 → 1100、セットビット数 = 2(素数)

解決のアプローチ

この問題を解くには、範囲内の各数値を順番に走査し、それぞれのセットビットの総数を調べます。C++では、あらかじめ用意されている関数 __builtin_popcount() を使うことで、セットビットの数を簡単に取得できます。

その後、取得したセットビット数が素数かどうかを判定し、素数であればカウントを1つ増やします。走査が終わった時点でのカウントが答えとなります。

素数判定のポイント

素数判定には、試し割り法を最適化した手法を使用します。2と3で割り切れるかどうかを先に確認し、その後は 6k±1 の形の数だけで割り算を試すことで、計算量を大幅に削減できます。

実装例

#include <iostream>
using namespace std;

bool isPrimeNumber(int n) {
    if (n <= 1) return false;
    if (n <= 3) return true;
    if (n % 2 == 0 || n % 3 == 0) return false;
    for (int i = 5; i * i <= n; i = i + 6)
        if (n % i == 0 || n % (i + 2) == 0)
            return false;
    return true;
}

void printPrimeSetBits(int l, int r) {
    int tot_bit, count = 0;
    for (int i = l; i <= r; i++) {
        tot_bit = __builtin_popcount(i);
        if (isPrimeNumber(tot_bit))
            count++;
    }
    cout << count;
}

int main() {
    int L = 7, R = 13;
    cout << "" << L << " から " << R << " の間でセットビット数が素数である数の総数 : ";
    printPrimeSetBits(L, R);
    return 0;
}

実行結果

7 から 13 の間でセットビット数が素数である数の総数 : 6

計算量について

このアルゴリズムの時間計算量は O((R − L + 1) × log R) です。各数値のポップカウントはビット長に比例した O(log n) で求められます。一方、セットビット数は32ビット整数でも最大32程度しかないため、素数判定は実質的に定数時間で完了するとみなせます。範囲が広くても効率的に動作する実用的なアプローチです。

  1. C++で二分木の各ノードのセットビット数を出力する方法

    二分木が与えられたとき、本記事で紹介する関数は、各ノードに格納されたキーの値を2進数に変換し、その2進表現に含まれるセットビット(1)の個数を返します。例キーとして 10、3、211、140、162、100、146 を持つ二分木を考えてみましょう。各キーの2進表現とセットビット数は以下のようになります。キー2進表現セットビット数(出力)101010230011221111010011514010001100316210100010310011001003146100100103__builtin_popcount 関数についてここでは GCC が提供する組み込み関数 __builtin_pop

  2. Pythonで2進表現のセットビット数が素数になる数を数える方法

    問題の概要 2つの整数LとRが与えられたとき、範囲[L, R](両端を含む)に含まれる整数の中で、2進表現におけるセットビット(1となっているビット)の個数が素数であるものを数える問題です。 例えば、入力がL = 6、R = 10の場合、出力は4となります。これは、以下の4つの数が条件を満たすためです。 6 → 110(セットビット数:2) 7 → 111(セットビット数:3) 9 → 1001(セットビット数:2) 10 → 1010(セットビット数:2) なお、8は2進表現で1000となり、セットビット数が1(素数ではない)ため対象外です。 解法のアプローチ この問題は、次の手順で解