問題概要
問題ページ
-
C - Next Prime
問題ページへ移動する
問題文
\(X\) 以上の素数のうち、最小のものを求めよ。
注記
素数とは、\(2\) 以上の整数であって、\(1\) と自分自身を除くどの正の整数でも割り切れないようなもののことです。
例えば、\(2, 3, 5\) は素数ですが、\(4, 6\) は素数ではありません。
制約
- \( 2 \le X \le 10^5 \)
- 入力はすべて整数
問題の考察
\(X\) 以上の素数のうち、最小のものを求める問題で素数の定義も注記で書いてある。
素数の定義通りにコーディングすると次のようになる。
素数を定義通り求める
- \(X\)が素数の場合
- \(2\)~\(X-1\)のいずれの数でも\(X\)が割り切れない
- for文を使って\(2\)から\((X-1)\)で\(X\)を割ってみる
この解き方でも\(X\)が小さい問題であれば特に問題にならないが、\(X\)が大きくなるにつれて計算量が増大する。
単純に、\(100,000\)の素数判定に係る時間は\(10\)の判定時間の\(10,000\)倍もかかる。
実際にコードを書いて見れば分かるが、この問題の制約ではTLE
してしまうので計算量の削減が必要になる。
実はこの判定のための計算量は次のように減らすことができる。
素数判定の計算量削減
- for文を使って\(2\)から\(\sqrt{X-1}\)で\(X\)を割ってみる
詳しくはこちらの解説を参照して下さい。
-
【python/アルゴリズム】素数を基礎から解説
続きを見る
たびすけ
他にも「エラトステネスの篩」で素数リストを求める方法もあります。
下の「参考」でコードも掲載してるので確認してみてね。
下の「参考」でコードも掲載してるので確認してみてね。
ACコード
import sys
def solve():
input = sys.stdin.readline
mod = 10 ** 9 + 7
x = int(input().rstrip('\n'))
for i in range(x, 10 ** 10 + 1):
is_prime = True
for j in range(2, int(i ** 0.5 + 1)):
if i % j == 0:
is_prime = False
break
if is_prime:
print(i)
exit()
if __name__ == '__main__':
solve()
参考
気になったので素数の出現頻度がどの程度なのか確認してみた。
エラトステネスの篩で素数の最大間隔を求めてみる
エラトステネスの篩で\(100,000\)までの素数リストを作成し、各素数の出現間隔の最大を求めるめてみました。
import sys
def solve():
input = sys.stdin.readline
mod = 10 ** 9 + 7
prime_list = [True] * (10 ** 5 + 1)
prime_list[0] = False
prime_list[1] = False
res = []
for i in range(2, 10 ** 5 + 1):
if prime_list[i]:
res.append(i)
for j in range(i, 10 ** 5 + 1, i):
prime_list[j] = False
max_diff = 0
for i in range(1, len(res)):
max_diff = max(max_diff, res[i] - res[i-1])
print(max_diff)
if __name__ == '__main__':
solve()
出力結果
72
ということで\(100,000\)までの各素数の出現間隔は最大でも100未満だと分かりました。
たびすけ
気になったことを実際にコーディングして確かめてみることは重要です!
素数の分布は数学の世界でも重要な関心事となっていますね!
素数の分布は数学の世界でも重要な関心事となっていますね!