2017年3月16日木曜日

プロジェクトオイラー 問123

プロジェクトオイラー(Project Euler)の問題をpythonでやってみます。
日本語翻訳サイトは、プロジェクトオイラー日本語 でネット検索です。


問123「素数の自乗で割った余り」
pn を n 番目の素数とする. (p1 = 2, p2 = 3, ...)
r を (pn - 1)n + (pn + 1)n を pn2 で割った余りとする.


例えば, n = 3 のとき, p3 = 5 であり, 43 + 63 = 280 ≡ 5 mod 25.
余り r が 109 より大きくなる n の最小値は 7037 である.
余り r が 1010 より大きくなる最初の n を求めよ.



注意!!!
自力で解きたい人へ
以降の記述には解法に関するネタバレが含まれます。




私の回答例は以下の通りです。
def f(rmin):
	for i, p in enumerate(P()):
		n = i + 1
		if n % 2:
			r = (2*n*p) % (p*p)
			if r > rmin: return n, p, r
		
def P():
	L, i = [2], 1
	yield 2
	while True:
		i += 2
		for j in L:
			if not i%j: break
		else:
			L.append(i)
			yield i
			
if __name__=="__main__":
	rmin = 10**10
	n, p, r = f(rmin)
	print "n =", n, "(素数p =", p, ", 余りr =", r, ")"



1.関数f(rmin)
・最小の余りrminを受け取り、問題に合うn番目の素数pとそのときの余りrについて、n,p,rを返します。


・この問題は問120の続きの問題です。
 問120では、

(a - 1)n + (a + 1)n を n2 で割った余りをrとしていましたが、
 本問では、

(pn - 1)n + (Pn + 1)n を pn2で割った余りをrとしています。

問120の式に、a=pnを代入すると以下のことがわかります。
 余りrは、nが偶数か奇数かでパターンが異なります。
 nが偶数の場合、余りrはaに関わらず 2 です。
 nが奇数の場合、余りrは 2npn をpn2で割った余りです。
 
・pは素数なので、2以外はすべて奇数です。
 題意から答えは明らかに2よりも大きく、必ず奇数です。
 このため、nが偶数のときは処理せず飛ばします。


2.関数P()
・素数を小さい方から昇順に返すジェネレーターです。呼び出しの都度、次の素数を返却します。

問108で作成した関数を改良しました




解答はこのすぐ下の行です。文字の色を白にしてます。選択状態にすると見えます。
n = 21035 (素数p = 237737 , 余りr = 10001595590 )

0 件のコメント:

コメントを投稿