C++で[1, N]の範囲に含まれる一意な素因数の最大個数を求める方法
この記事では、与えられた範囲 [1, N] 内の数が持ちうる「一意な素因数(重複しない素因数)」の最大個数を求める問題を扱います。
まず、例を使って問題を具体的に理解しましょう。
入力例と出力例
- 入力 − N = 100
- 出力 − 3
説明 − 範囲 [1, 100] の中から 30 を考えてみます。
30 = 2 × 3 × 5 となり、素因数はすべて異なる3つです。したがって、範囲 [1, 100] において一意な素因数は最大で3個存在します。
- 入力 − N = 300
- 出力 − 4
N = 300 の場合は、2 × 3 × 5 × 7 = 210 ≤ 300 となるため、4つの異なる素因数を持つ数(210など)が範囲内に存在し、答えは4になります。
アルゴリズムの考え方
このプログラムでは以下の手順で問題を解きます。
- 関数 MaxPrime() の冒頭で、N < 2 であるかどうかを判定します。該当する場合は 0 を返して終了します。
- 次に、エラトステネスの篩(ふるい)を用いて、N までのすべての素数を求めます。
- 積を格納する変数 pro = 1 と、最終的な答えを格納する変数 max = 0 を int 型で初期化します。
- エラトステネスの篩の処理の中で、pro *= p; と書くことで、積が N より小さくなっている間、先頭から順に素数を掛け合わせていきます。
- pro > N となった時点で max を返します。それ以外の場合は max に 1 を加算します。
- 篩の処理が完了した後も、最後に max を返します。
C++による実装例
#include <bits/stdc++.h>
using namespace std;
int MaxPrime(int N){
if (N < 2)
return 0;
// エラトステネスの篩を使用
bool Arr[N+1];
memset(Arr, true, sizeof(Arr));
int pro = 1, max = 0;
for (int p=2; p*p<=N; p++){
if (Arr[p] == true){
for (int i=p*2; i<=N; i += p)
Arr[i] = false;
/* 積がNより小さい間、先頭の素数を掛け合わせる */
pro *= p;
if (pro > N)
return max;
max++;
}
}
return max;
}
// メイン関数
int main(){
int N = 300;
cout << MaxPrime(N);
return 0;
}
実行結果
上記のコードを実行すると、次の出力が得られます。
4
補足:なぜこの方法が正しいのか
異なる素因数をできるだけ多く持つには、できるだけ小さな素数から順に掛け合わせた数(最小の数)が範囲内に収まるかを確認すればよいことになります。つまり、2 × 3 × 5 × 7 × … というように小さい素数から順番に掛けていき、その積が初めて N を超えた直前の素因数の個数が答えとなります。計算量はエラトステネスの篩により O(N log log N) 程度に抑えられ、効率的に求められます。
-
C++のCHAR_BITとは?意味と使い方を解説
CHAR_BITは、char型が持つビット数を表すマクロです。C++では「limits.h」ヘッダーファイル(C++では<climits>)で宣言されており、一般的な環境では1バイトが8ビットであることを示します。このマクロを利用することで、移植性の高いコードを書くことができます。環境に依存せずにchar型のビット数を取得できるため、ビット演算やデータサイズの計算に役立ちます。CHAR_BITの使用例以下は、C++でCHAR_BITを使用したサンプルコードです。CHAR_BITとsizeofを組み合わせてint型の全ビット数を求め、整数値を2進数形式で出力しています。#includ
-
Pythonで数値の一意な素因数の積を求める方法
この記事では、以下の問題文に対する解決策について学びます。問題文数値 n が与えられたとき、その数値が持つすべての一意な素因数の積を求めて返します。例入力: num = 11 出力: 積は 11説明ここでは、入力された数値は 11 であり、素因数は 11 のみです。したがって、その積は 11 となります。アプローチ1:総当たり法i = 2 から n+1 までの for ループを使用し、i が n の因数であるかどうかを確認します。因数であれば、さらに i 自体が素数かどうかを判定し、素数であれば product 変数に積を格納します。この処理を i が n になるまで繰り返します。コード例de