与えられた仮説を反証する数を見つけるためのC++コード
正の整数 n が与えられたとします。ここで、「ある正の整数 n が存在し、任意の正の整数 m に対して (n・m + 1) が常に素数となる」という仮説を考えます。この仮説が誤りであることを証明するには、反例となる m を見つける必要があります。
例えば、入力が n = 12 の場合、出力は 10 になります。これは 12 × 10 + 1 = 121 が素数ではないためです(121 = 11 × 11 と素因数分解できるからです)。
解法のアプローチ
この問題は、以下のシンプルな手順で解くことができます。
- n が 3 未満の場合:n + 2 を返す
- それ以外の場合:n - 2 を返す
if n < 3, then:
return n + 2
Otherwise
return n - 2
なぜこれで反例になるのか?
この方法が機能する理由は数学的にきれいに説明できます。n ≥ 3 のときに m = n - 2 を選ぶと、次のようになります。
n・(n - 2) + 1 = n² - 2n + 1 = (n - 1)²
つまり結果は完全平方数となり、n - 1 ≥ 2 であるため必ず合成数になります。同様に、n < 3 の場合に m = n + 2 を選ぶと、n・(n + 2) + 1 = (n + 1)² となり、やはり素数ではありません。したがって、どのような n に対しても反例が必ず存在することになります。
C++による実装例
理解を深めるために、以下の実装例を見てみましょう。
#include <bits/stdc++.h>
using namespace std;
int solve(int n){
if (n < 3)
return n + 2;
else
return n - 2;
}
int main(){
int n = 12;
cout << solve(n) << endl;
}
入力
12
出力
10
このように、複雑な素数判定を行わなくても、代数的な性質を利用すれば O(1) の計算量で反例を求められます。
-
C++で指定した数以下の最大の特殊素数を求める方法
問題の概要 ある数 n が与えられたとき、n 以下の最大の「特殊素数」を求めることを考えます。特殊素数とは、桁を一つずつ付け加えて構成したとき、その過程で現れるすべての数(先頭からの接頭辞)が素数となる数のことです。 たとえば 379 は、3・37・379 のいずれも素数であるため特殊素数です。一方、途中の数に素数でないものが含まれる数は、特殊素数とはみなされません。 アルゴリズムの考え方 ここではエラトステネスの篩(ふるい)を使用します。まず n までの素数表(篩配列)を作成し、その後、N から順に数を減らしながら以下の手順で判定を行います。 その数が素数かどうかを確認する 素数であれば
-
C++でnCrが指定された素数で割り切れるかどうかを判定する方法
3つの変数 N、R、P があるとします。N と R から二項係数 NCR を求め、P は素数とします。このとき、NCR が P で割り切れるかどうかを判定するのが本記事の目的です。例えば、N = 7、R = 2、P = 3 の場合、7C2 = 21 となり、21 は 3 で割り切れるため、結果は true となります。二項係数は一般的に次の式で表されます。NCR = N! / (R! × (N − R)!)ここでルジャンドルの定理(Legendres Formula)を活用します。この定理を使うと、N!、R!、(N − R)! のそれぞれを割り切る素数 P の最大のべき乗(指数)を求めることが