質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

2915閲覧

modpowがわからない

kyokio

総合スコア560

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2020/05/13 14:02

###modpowを高速で計算したい

プログラミングの問題でn^m(modP)を計算する時、1回ずつnをm回かけるとTLEになってしまいました。
(Pythonだと勝手にやってくれる関数あるらしい)
調べてみると1回のループで1回かけるのではなく複数回かけるといいらしいというのを知りました。
そりゃそうですが

参照元URLでは、二進数とbit演算で高速に処理していました。

以下が参照元URLのコードです。

ll modpow(ll a, ll n=mo-2) { ll r=1; while(n) r=r*((n%2)?a:1)%mo,a=a*a%mo,n>>=1; return r; }

いまいちやってることがわからないから出力してみた

とりあえず、それぞれの変数をcoutで各変数を出力してみました。
mはシフトしてるので2進数で出力しました。

ll modpow(ll n, ll m=mod-2) { ll r=1; while(m){ cout << "r:" << r << endl; cout << "m:" << bitset<16>(m) << endl; cout << "n:" << n << endl << endl; r=r*((m%2)?n:1)%mod,n=n*n%mod,m>>=1; } return r; }

出力結果は以下になります。
modpow(99,99):
出力結果

わからないこと

m>>=1はシフト演算で右に1シフトしてるのはわかります。(桁を1つ小さくしてる感じ)

(m%2)?n:1)は3項演算子で今見てるbitが1(奇数)ならn0なら1rにかけるということだと思います。
n=n*n%modnnをかけてmodをとってる。
それぞれの式の意味はわかりますが、全体で何をやってるのかわからない。

分かる方教えていただけるとありがたいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

この回答において記号^は累乗を意味します。

x^(a + b) = (x ^ a) * (x ^ b)を利用します。

x^(2n) = (x ^ n) ^ 2となり、x^(2n + 1) = x * ( (x ^ n) ^ 2)となります。これを利用すれば、計算を随分と省略できます。

例えば(x ^ 1024)の場合、

x ^ 2 → x ^ 4 →x ^ 8 →x ^ 16 →x ^ 32→x ^ 64→x ^ 128→x ^ 256 →x ^ 512→ x^ 1024

と大分計算回数が節約できます。二で割った余りで条件分岐しているのは端数処理のためです。

投稿2020/05/13 14:15

HogeAnimalLover

総合スコア4830

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

episteme

2020/05/13 14:38

それに加えて: a * b (mod P) = (a mod P) * (b mod P) だから 「複数回のかけ算を済ませて最後に mod P」ではなく 「一回のかけ算ごとに mod P」することで 計算途中の値も常にP以下になる。 (途中で桁あふれを起こさない) ...を利用してますね。
kyokio

2020/05/15 08:33

ありがとうございます。 わかってきました! ですが、modpowの引数にm=mod-2としているのは逆元を計算にこの関数を使う際にmod-2を打たなくても良くするためと考えていいのでしょうか?
episteme

2020/05/15 09:22

それは書いたヒトに訊いて。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問