C++で素数階乗(プリモリアル)を求めるプログラムの解説
素数階乗(プリモリアル)とは?
この問題では、数値 n が与えられ、その素数階乗(プリモリアル)を求めて出力することが課題となります。
素数階乗(Primorial、Pn#)とは、「最初の n 個の素数をすべて掛け合わせた数」のことです。
素数階乗は、通常の階乗(n!)とよく似た概念です。両者の違いは、階乗が任意の整数を順に掛けるのに対し、素数階乗では素数のみを掛け合わせる点にあります。
問題の例
具体例を見てみましょう。
入力:N = 4
出力:210
説明:素数階乗 Pn# = 2 × 3 × 5 × 7 = 210
解き方のアプローチ
この問題を解くには、以下の手順で進めます。
- 最初の n 個の素数をすべて求める
- それらの素数の積を計算する
- その積が素数階乗の値となるので出力する
素数の列挙には、エラトステネスの篩(ふるい)を最適化した手法を用いることで、効率よく素数リストを作成できます。
C++での実装例
上記の考え方を実装したプログラムがこちらです。
#include<bits/stdc++.h>
using namespace std;
const int MAX = 1000000;
vector <int> primeNumbers;
// 素数を事前にすべて求める関数
void findPrimes() {
bool marked[MAX/2 + 1] = {0};
for (int i = 1; i <= (sqrt(MAX)-1)/2 ; i++)
for (int j = (i*(i+1))<<1 ; j <= MAX/2 ; j += 2*i +1)
marked[j] = true;
primeNumbers.push_back(2);
for (int i=1; i<=MAX/2; i++)
if (marked[i] == false)
primeNumbers.push_back(2*i + 1);
}
// 素数階乗を計算する関数
int findPrimorial(int n) {
findPrimes();
int result = 1;
for (int i=0; i<n; i++)
result = result * primeNumbers[i];
return result;
}
int main() {
int N = 6;
cout<<"Primorial(P#) of first "<<N<<" prime numbers is "<<findPrimorial(N)<<endl;
return 0;
}
実行結果
Primorial(P#) of first 6 prime numbers is 30030
コードのポイント
- findPrimes() 関数:奇数のみを扱うことでメモリ使用量を半分に抑えたエラトステネスの篩を実装しています。まず 2 を素数リストに追加し、その後マークされていない奇数を素数として登録していきます。
- findPrimorial() 関数:生成した素数リストの先頭から n 個の素数を取り出し、順番に掛け合わせることで素数階乗を計算します。
なお、素数階乗は非常に大きな値になりやすいため、n が大きくなると int 型ではオーバーフローする可能性があります。実用上は long long 型や多倍長整数の利用を検討するとよいでしょう。
-
C++で可変数の引数(可変長引数)を扱う方法
プログラミングをしていると、引数の個数があらかじめ決まっていない関数、つまり呼び出しのたびに異なる数のパラメータを受け取れる関数が必要になる場面があります。C/C++ではこのような状況に対応する仕組みが用意されており、要件に応じて可変個の引数を受け取る関数を自由に定義できます。以下に、そのような関数の定義例を示します。 int func(int, ... ) { . . . } int main() { func(1, 2, 3); func(1, 2, 3, 4); } 注目すべきは、関数func()の最後の引数が省略記号(ピリオド3つの「...」)になってい
-
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