Problem 188
の下8桁を求めよ。
ヒント1: 桁だけでメモリが死ぬので直接計算してはいけません
ヒント2: 冪乗演算子は右結合なので左から計算してはいけません
#
n 1777
for (i in 1:1855) n n^1777 mod 1e8
1777 ⇈ 1855
35 / 40
Slide 36
Slide 36 text
オイラーの定理
と を互いに素な正整数とします。このとき次の関係が成立します。
はオイラーの (トーシェント)関数というもので、 以下の自然数で
と互いに素な自然数の個数を返します。
例) なら1と5が互いに素なので 。 とすると、
となってオイラーの定理が成り立つ。
a n
a
φ(n)
mod n = 1
φ(n) φ n
n
n = 6 φ(6) = 2 a = 5
5
2
mod 6 = 1
36 / 40
Slide 37
Slide 37 text
で?
1777は素数なので、1e8と互いに素です。つまり次の関係が成り立ちます。
乗する度に下8桁が00000001に戻るということです。つま
りこうです。
指数部分の剰余をとってから計算して良いということです。
1777
φ(10
8
)
mod 10
8
= 1
φ(10
8
) = 4 × 10
7
1777
x
mod 10
8
= 1777
x mod 4×10
7
mod 10
8
37 / 40
Slide 38
Slide 38 text
コードにするとこう
solve function(a, b, m) {
ans = 1
for (i in seq_len(b)) {
if (i b) m = 1e8
ans = modpow(a, ans, m)
}
return(ans)
}
solve(1777, 1855, 4e7)
※冪乗の剰余を計算する関数がRには無いので適当に定義する必要がありま
す。メンドイ!!
38 / 40
Slide 39
Slide 39 text
実は…
ループは10回で良い
で剰余とっても良い
Pythonだと楽
x = 1
for i in range(10):
x = pow(1777, x, 10 8)
print(x)
とかいろいろあって闇が奥が深いです。問題解いてからforum覗いてみるとよ
いでしょう。
10
8
39 / 40