素数判定
概要
与えられた数が素数かどうか判定するアルゴリズム。
試し割り法。
アルゴリズム内容
素数とは、正の約数が $1$ と自分自身しかないような $2$ 以上の整数のこと。
つまり、$n$ が素数かどうか判定するには、$2$ から $n-1$ までどれでも割り切れないことを確認すればよい。
だが、この方法、実は少し工夫ができる。
例えば $299$ が素数かどうか判定する場合。
$299$ は $23$ で割り切れるのだが、実は $299/23=13$ である。
ということは、$13$ を見つけることができるなら $23$ を試す必要がない。
よって、平方して $299$ を超えてしまう $18$ 以上を調べなくてもかまわない。
つまり、$2$ から $298$ までではなく、$2$ から $17$ まで割り切れなければ素数と判断してしまってよい。
これにより、$O(n)$ ではなく $O(\sqrt{n})$ で素数かどうかを判定できる。
もちろん、B問題のように計算量を気にしなくてもいい場合は、$n-1$ まで割ってみてもいい。
C++での実際の参考コードは以下。
bool is_prime (long long n) {
if (n<2) return false;
if (n%2==0&&n>2) return false;
for (long long i=3; i*i<=n; i+=2) {
if (n%i==0) return false;
}
return true;
}
注意点
多数の判定には不向き。
この方法は、$1$ つめの判定結果が $2$ つめの判定に何も役立たない。
そのため、判定したい個数が多いとそれに比例して時間がかかる。
その場合は「エラトステネスの篩」の記事参照。(D問題レベル)
また、合わせ技で「$\sqrt{n}$ 以下の素数をエラトステネスの篩で探して試し割りをする」ということもできる。
ほどほどの個数だとこれが一番速い場合もある。
関連知識
エラトステネスの篩
$n$ 未満の全ての素数を洗い出すアルゴリズム。
判定したい個数が多いなら、あちらを使った方が全体としては速い場合もある。
素因数分解
どんな素因数が含まれているかまで調べるやつ。