(問題 3) 逆元 Clojure(Beta)編(paizaランク B 相当)
問題にチャレンジして、ユーザー同士で解答を教え合ったり、コードを公開してみよう!
問題
下記の問題をプログラミングしてみよう!
(mod P 上の逆元について)
問題 1 では、掛け算、足し算、引き算について行ってきました。
ここでは割り算について見ていきます。素数 P と 1 以上 P - 1 以下の整数 X に対し、 X × Y = 1 (mod P) となる Y (1 ≦ Y ≦ P - 1) が必ず 1 つずつ存在します。このとき、Y を X の逆元と呼びます。
mod P 上の演算で X を Y で割ることは、X に Y の逆元をかけることを意味します。
例として P = 5 とします。3 × 2 = 1 (mod 5) となるので、3 の逆元は 2 です。 1 の逆元は 1 × 1 = 1 (mod 5) となるので、1 となります。
また、2 ÷ 3 = 2 × 2 = 4 (mod 5) となり、4 ÷ 1 = 4 × 1 = 4 (mod 5) となります。
では、実際に逆元はどのように計算するのでしょうか。これは、問題2で学んだ高速なべき乗計算(繰り返し二乗法)を用いることで効率的に求めることができます。
逆元の計算はフェルマーの小定理を用います。フェルマーの小定理とは P が素数で a,P が互いに素なとき、a ^ (P - 1) = 1 (mod P) であるという定理です。
フェルマーの小定理により、1 以上 P - 1 以下の整数 X に対し、X × X ^ (P - 2) = 1 (mod P) が成り立つので、mod P 上での X の逆元は X ^ (P - 2) (mod P) であることがわかります。
先ほどの例では、3 の逆元は 3 ^ (5 - 2) = 2 (mod 5) と計算できます。
では実際に逆元を計算してみましょう。
(問題)
素数 P と Q 個の整数 q_1,q_2,...,q_Q が与えられます。1 ≦ i ≦ Q に対して、mod P 上での q_i の逆元を求めてください。
- 入力される値
-
入力は以下のフォーマットで与えられます。
P Q
q_1 q_2 ... q_Q
- 1 行目には 2 つの整数 P,Q が与えられます。
- 2 行目には Q 個の整数 q_1,q_2,...,q_Q が与えられます。
- 入力は合計で 2 行からなり、入力値最終行の末尾に改行が 1 つ入ります。
入力値最終行の末尾に改行が1つ入ります。
文字列は標準入力から渡されます。
標準入力からの値取得方法はこちらをご確認ください
- 期待する出力
1 行で出力してください。
1 ≦ i ≦ Q において、q_i の逆元を p_i とすると、p_1,p_2,...,p_Q を空白区切りで出力してください。
- 条件
-
すべてのテストケースにおいて、以下の条件をみたします。
- 10 ^ 8 ≦ P ≦ 2 × 10 ^ 9
- 1 ≦ Q ≦ 200000
- 1 ≦ q_i ≦ P - 1 (1 ≦ i ≦ Q)
- P は素数
- 入力例1
-
998244353 6
1 2 3 4 5 6
- 出力例1
-
1 499122177 332748118 748683265 598946612 166374059
問題一覧へ戻る