mod pでの平方根
QS での因数分解では
を解きたいわけです。とはいえ 0 から
平方剰余
そもそも剰余環での平方根は存在するかを確認しておく必要があります。というのも
なので
ではその存在確認をどのようにするかというと、平方剰余というものを求めます。
という計算で、結果は 1 か -1 になります。(フェルマーの小定理
この
\bmod p での平方根
そして肝心の平方根の求め方ですが、以下のようになります。計算効率の観点から
p \equiv 3, 7 \pmod8 の場合
x = a^{(p+1)/4} \bmod p -
return
x
p \equiv 5 \pmod8 の場合
x = a^{(p+3)/8} \bmod p -
ならばx^2 \not\equiv a \pmod p x = x \cdot 2^{(p-1)/4} \bmod p
-
return
x
p \equiv 1 \pmod8 の場合
-
として非平方剰余を選ぶd -
としてp-1=2^st ,s を定める。ただしt は奇数t A \equiv a^t D \equiv d^t m = 0 - For
ini [0,s) - if
(AD^m)^{2^{s-1-i}} \equiv -1 m = m + 2^i
- if
x \equiv a^{(t+1)/2}D^{m/2} -
return
x
最後の
また、数式中に度々現れる剰余環でのべき乗については繰り返し二乗法で求められます。
int32 ModPow(int32 a0, int32 e, int32 p) {
int64 r = 1;
for (int64 a = a0; e; e >>= 1) {
if (e & 1) r = r * a % p;
a = a * a % p;
}
return r;
}
p \equiv 1 \pmod8 の場合その 2
書籍でもう 1 つ計算法が紹介されていたのでこちらも紹介します。まずアルゴリズムをそのまま書くと
-
が非平方剰余となるt^2-a を選ぶt x=(t+\sqrt{t^2-a})^{(p+1)/2} \pmod{p^2} -
return
x
となるわけですが、数式中に平方根が出てきています。これは
文字が多くなると大変なので
何となく雰囲気に覚えはありませんか?複素数で
となります。試していませんし証明できているわけでもないですが、恐らく
template <typename T>
using IntInF = std::pair<T, T>;
// 動作未確認です
int32 PowModInF(IntInF<int32> a0, int32 e, int32 p) {
IntInF<int64> r {1, 0};
for (IntInF<int64> a {a0.first, a0.second}; e; e >>= 1) {
if (e & 1) {
r = IntInF<int64> {
(r.first * a.first + r.second * a.second % p * omega) % p,
(r.first * a.second + r.second * a.first) % p
};
}
a = IntInF<int64> {
(a.first * a.first + a.second * a.second % p * omega) % p,
2 * a.first * a.second % p
};
}
return r;
}
\bmod p^k での平方根
まず
するとこの 3 式を混ぜることで
となります。この最初と最後を
さらに
となり
参考文献
- "Prime Numbers" by Richard Crandall (Springer, 2005) (邦訳版もあります)
- "Prime Numbers and Computer Methods for Factorization" by Hans Riesel (Birkhauser, 1994)
Discussion