数学

有限体Fp上での1のn乗根を求める

3n+1型の素数には三乗根があります。それは原始根をeとすれば 1, w=e^(p-1)/3 および w^2と求まるのですが、求めるだけならば原始根は知らなくても問題ありません。フェルマーの小定理からFpの任意の元aについて

a^(p-1) = 1

なのですから a^(p-1)/3 はあと3乗すれば1になる数、すなわちそれは1かwかw^2のいずれかです。よって適当に数を選んで(p-1)/3乗してみれば2/3の確率で求まります。原始根を求めるのは大変なので大きな素数pに対してはこちらのほうが簡単でしょう。

同じ理論が 素数の羃乗根(たとえば4乗根とか)にも使えます。

4n+1型の素数は4乗根があります。さきほど同様原始根をeとすれば 1, w=(p-1)/4、w^2, w^3が4乗根です。しかしw^2は2乗根であり、それは-1で自明な根です。自明でない4乗根(すなわち原始4乗根はwと w^3になります)よって、ランダムに選んだ数を(p-1)/4乗してみれば、1/2の確率で原始4乗根が得られることになります。

例1)
F13を考えます。12 = 3 * 2^2ですからF13は4乗根をもちます。実際

2^3 = 8

で、8は2乗根ではないから(原始)4乗根です。

例2)
F97は 97-1 = 3 * 32ですから32 乗根を持ちます。

よって、F97の任意の元を選び3乗すれば32乗根のうちのどれかに属します。その数をrとします。
これくらい大きくなるとそれが原始的かどうか(つまり32乗して始めて1になるのか)チェックするのは結構大変に思えます。
普通に考えれば rが原始32乗根であるには

r≠1
r^2≠1
r^4≠1
r^8≠1
r^16≠1

であることを確認すればよいのですが。しかしよく注視してみると

r^16≠1

だけチェックすればよいことがわかります。なぜなら r^16≠1ならば r^8≠1 だからです。
よって

r^16 = (a^3)^16 = a^48 ≠ 1

だけのチェックをすればよく、このチェックを通過した数は F97における1の原始32乗根です。
なおこのチェックは2の羃に関しては平方剰余かどうかをチェックしているのと同じというのがまた味わい深いですね。

これで計算してみると

2^48=1
3^48=1
4^48=1
5^48=96

よって、5^3 = 28がF97の原始32乗根ということになります。

例3)
F433は

p-1 = 432 = 16 * 3^3

よって F433は 27乗根をもちます。よって任意にaを選び16乗すればそれは27乗根の1つです。
原始27乗根であるかどうかチェックするには

r≠1
r^3≠1
r^9≠1

をチェックすればよいのですが、同様の理論により
r^9≠1だけをチェックすればよいことがわかります。
実際計算してみると

(2^16)^9 = 1
(3^16)^9 = 198

であり、3^16 = 26が F433の 原始27乗根として求まります

確率的なアルゴリズムではありますが「あたり」を引く確率は高いので、総じて計算は早いといえましょう。

Posted by issei

カテゴリ: 数学

3n+1の素数と二元二次不定方程式

3n+1型の素数pについて x^2 + 3y^2 = p となる整数を求めるアルゴリズムのメモ。解があることの証明は結構面倒なんで略します。

そもそも x^2 + 3y^2 <=p なる数は有限なのだから、全ての数について調べていけば解は見つかるわけですが、pが巨大な数になると探索は非常に困難になります。そこで、このエントリではpが巨大な数でも比較的少ない計算量で求める方法を紹介します。

基本的な手法としては4n+1型の素数についての平方和 x^2 + y^2 = p の解を求めるのと同じです。

流れ

x^2 + 3y^2 = N p --(1)

となるNを探します。そこからより小さいNを探し最終的にNを1にすることで求めます。(1)式は x, yの範囲として

-p/2 < x < p/2
-p/2 < y < p/2

と出来ることに注意します。(もし一つでも解が見つかれば x = x % p, y = y % pとすればよいのです。

x^2 + 3y^2 < (p/2)^2 + 3(p/2)^2 < p^2 より

N p < p^2

すなわち

N < p

となるようにNを選べることに注意します。

アルゴリズムその1

ここで次の事実を用います。

Nもまた u^2 + 3v^2 の形に書くことができる。

証明は結構面倒なので略します。

よって(1)式は

x^2 + 3y^2 = (u^2 + 3v^2) p --(2)

と書き直せます。このような u, vを見つけることができれば(2)式は

p = (x^2 + 3y^2) / (u^2 + 3v^2)

= (x + √-3y)(x - √-3y) / (u + √-3v)(u - √-3v)

と書き直されます。(いきなり平方根とか虚数とか出てくるけど気にしない)。ここで次の事実を用います。

(x + √-3y) / (u + √-3v)

または

(x + √-3y) / (u - √-3v)

のどちらかは割りきれる。

証明は結構面倒なので略します。

ただこのやり方はpを分解するのに、Nが現れ、しかもそのNを分解するというのは本末転倒のように思えますが、実際にはNの素因数は3n+1型の素数または平方数しか現れません。さらに後述するように最初のx, yを選べば平方数を含まないようにすることもできます。また x, yの選び方から N < p となるので、Nの素因数分解が容易に出来るのであればpに比べて小さい数の分解が出来ればよく、結構高速に求めることができます。各素因子の分解についても同じように考えていけばよいのです。

ただ、pが大きな数の場合、Nも大きくなる傾向があり、探索が困難になることが考えられまs.そこで、素因数分解をしなくてもよいアルゴリズムを紹介します。

アルゴリズムその2

次のような数を探します

t^2 + 3s^2 = M N  --(3)

このような数はもうわかっていて、(1)のx, yがまさにそれです。ここで(1)同様 t, sは範囲として -N/2 から N/2の間に収めることが出来ることに注意します。(すなわち t = x % N, s = y % N とすればよいのです)

(1)式の両辺に(3)式の両辺 を掛ければ

(x^2 + 3y^2)(t^2 + 3s^2) = M N^2 p

左辺 = (x + √-3y)(x - √-3y) (t + √-3s)(t - √-3s)
= (x + √-3y)(t - √-3s)(x - √-3y)(t + √-3s)
= {xt + 3ys  + √-3(-xs + yt)}{xt + 3ys -√-3(-xs + yt)}
= (xt + 3ys)^2 + 3(-xs + yt)^2

ところで -xs + yt = 0 (mod N)です。故に (-xs + yt)はNで割りきれます。右辺はN^2で割りきれるから等式が成立するには (xt + 3ys)^2もNで割りきれないといけません。つまり、

x' = (xt + 3ys)/N
y' = (-xs + yt)/N

はどちらも整数です。よって

x'^2 + 3y'^2 = M p

となります。t, sの値の取り方から M<Nとなりますからより小さいMを見つけることが出来ました。以下これを繰り返せばMは最終的に1にすることができます。

最初のx, yの求め方

最後に(1)式をみたすx, yの探し方を紹介します。これには1の三乗根がw必要になります。これは原始根が分かっていれば簡単にわかります。

pの原始根をeとすれば pは 3n+1型だから体Kpにおいて、

w = e^n

とすればwは1の三乗根です。これより

(w - w^2)^2 = -3 (mod P)

となりますから(w^3=1に注意して計算してみるとよい)

x = (w - w^2)
y = 1

とすれば

x^2 + 3y^2 = 0 (mod P)

を満たすから

x^2 + 3y^2 = N P

なるNが見つかったことになります。

しかし三乗根を見つけるのに原始根を探すというのはいささか面倒です。これを解決するもっとシンプルな解法があります。適当な数をランダムに選びn乗すれば2/3の確率で1の三乗根になります。10個もトライすれば見つかるでしょう。

 

Posted by issei

カテゴリ: 数学

法Nでの逆数を求めるその3

一つ前のエントリ


法Nでの逆数を求めるその2


はつまるところ、

\[ax + by = 0 \pmod N\]

を考え$a, b$をどんどん小さくしてゆき、上記等式を満たすように$x, y$を変えていくアルゴリズムと言えるでしょう。ここで説明する手法は両辺を2で割りより早く$a, b$を小さくするという手法です。ところで一つ前のエントリの補題により$a, b$は互いに素です。よって$a, b$が共に偶数ということはありません。しかし例えば$a, y$が共に偶数なら

\[(a/2)x + b(y/2) = 0 \pmod N\]

と係数をより小さくすることができます。ここでちょっと工夫をします。$\pmod N$で考えるのなら上記の式は

\[ax + b(y+N) = 0 \pmod N\]

と$y$に$N$を足しても成立します。$N$が奇数ならば$y+N$は偶数になりますので、つまるところ$y$が偶数だろうが奇数だろうが、$a$が偶数ならば$a/2$を考える事が出来ます。$b$についても同様で$x$が偶数ならば$x/2$とすればよく、奇数ならば$(x+N)/2$を考えればよいのです。 この作業の結果$a, b$は共に奇数になるはずです。今借りに$a>b$とすれば $a' = a-b, b' = b$とさらに係数を小さくすることができます。$a-b$は偶数ですから必ず2で割れるのでさらに係数を小さくしていくことができます。この作業によりいつかはどちらかの係数は1になります。そのときの$x$が求める答えです。

このアルゴリズムは$N$が奇数のときにしか使えませんが、シフトと加算減算だけで実行できるのでとても高速です。

サンプルコード


#!/usr/bin/env ruby



def inv(t, n) a = n b = t x = 1 y = 0

while b != 1 shift = 0 while (b & (1 << shift)) == 0 if((x & 1) == 1) x = x + n end x /= 2 shift += 1 end b = b >> shift

shift = 0 while (a & (1 << shift)) == 0 if((y & 1) == 1) y = y + n end y /= 2 shift += 1 end a = a >> shift

if b > a x = x + y b = b - a else y = x + y a = a - b end end x end

n = 3801307799 (1..n).each do |t| s = inv(t, n) puts("#{t} * #{s} = #{t * s % n} (mod #{n})") end



Posted by issei

カテゴリ: 数学

法Nでの逆数を求めるその2

一つ前のエントリ

法Nでの逆数を求める

の手法は途中の計算結果を保存しておかないといけないという問題がありました。そこでそれを改良したアルゴリズムを紹介します。このアルゴリズムもユークリッドの互除法を使うという点では同じです。違うのは

\[ax + by = 1\]

ではなく

\[ax + by = N\]

を考えている点がです。この式は \[a=N, b=n\] とすると \[x=1, y=0\] という自明な解を持っています。

そこで \[a_1 = N, b_1 = n, x_1 = 1, y_1 = 0\] として前回と同じように

\[ a_{n+1} = b_n\\ b_{n+1} = m_n\\ x_{n+1} = d_n x_n + y_n\\ y_{n+1} = x_n \] と変形していきます。 \[ a_n x_n + b_n y_n = N \] が常に成り立っているので、

\[ a_n x_n = N - b_n y_n \] が成立します。 \[ a_n = b_{n-1}, y_n = x_{n-1} \] ですから \[ b_{n-1} x_n = N - b_n x_{n-1} \] と書き直すことができます。nを2からnまで変化させた等式

\[ b_1 x_2 = N - b_2 x_1\\ b_2 x_3 = N - b_3 x_2\\ \dots\\ b_{n-1} x_n = N - b_n x_{n-1} \]

について左辺どうし、右辺どうしを掛け合わせると

\[左辺 = b_1 b_2 \dots b_{n-1} x_2 x_3 \dots x_n \] \[右辺 = N(なんちゃら) \pm b_2 b_3 \dots b_{n} x_1 x_2 \dots x_{n-1} \]

となります。 $\pmod N$で考えれば $N(なんちゃら)$は0とみなせるので結局

\[b_1 x_n = \pm b_n x_1 \pmod N\]

が常に成立していることになります。符号はnの偶奇で決まります。なお $b_1, b_2, ...$ および $x_1, x_2, ...$がゼロでないという証明が別途必要ですがそれは最後に記します。

ところで、$b_n$はいずれ1になります。$x_1 = 1, b_1 = n$でしたから、その時点で

\[n x_n = \pm 1\]

となり $x_n$が求める解になります。このアルゴリズムは途中の計算結果を保存しておかなくてよいという利点があり一つ前のエントリより優れていると言えましょう。

サンプルコード


#!/usr/bin/env ruby
    
n = a = 916132831
b0 = b = 9973
x = 1
y = 0
sign = 1

while b != 1
  d = a / b
  m = a % b
  
  a = b
  b = m
  
  tmp = d * x + y
  y = x
  x = tmp
  
  sign = -sign
end

puts("#{sign * x} * #{b0} = #{b0 * x * sign % n} (mod #{n})")

さて、このアルゴリズムでも十分実用になるのですが、Nが奇数の場合はさらに効率よく求めることができます。 そのアルゴリズムを次のエントリで紹介しようと思います。

補足

$b_1, b_2, ...$ および $x_1, x_2, ...$がゼロでないという証明

$b_n$については単調に減少し1になったところでアルゴリズムは止まるので0でないことは明らか。 $x_n$については次の補題を利用します。

補題

\[ \hbox{gcd}(a_{n+1}, b_{n+1}) = \hbox{gcd}(a_n, b_n)\\ \hbox{gcd}(x_{n+1}, y_{n+1}) = \hbox{gcd}(x_n, y_n)\\ が成立する \]

この補題より$\hbox{gcd}(x_n, y_n) = \hbox{gcd}(x_1, y_1) = 1$であり、したがって $x_n=0$ならば$y_n=1$でならねばならず それは$b_n=0$でなければならないので矛盾

Posted by issei

カテゴリ: 数学

法Nでの逆数を求める

と書くと何やら難しそうですが、簡単にいうならば$n$という整数が与えられたとき

\[nx = 1 \pmod N\]

となる数$x$を見つけようということです。このような逆数はnとNが互いに素なら必ずあります。法Nにおける逆数は整数の剰余の計算においてとても重要であり暗号の分野で頻繁に使われています。

(多くの)プログラム言語的に言い換えると

(n * x) % N = 1

となる数ということになるでしょう。ここで 細かいことをいうと$n$が負数のときどうなるん?という問題があります。例えばperlやrubyだと $n$が負の場合は(例えば -1 % 7)は 6を返しますが、CやNode.jsは-1を帰すようです。 ちなみに、数学的にはどちらでも問題なしです。何故どちらでもいいかを語り始めると長いので細かいことは有限体の本でも読んでもらうとして、結論から言うと

\[-1 = 6 \pmod 7\]

と思っておけば問題ないです。7を法とした世界では-1も6も同じものを指します。表現の仕方が違うだけです。

さてこのアプローチには大きく2種類あるようです。 一つはユークリッドの互除法を使うもの。もう一つはopensslの内部て使われているものです。後者のアルゴリズムに名前があるのかどうかはしりません。

最初にユークリッドの互除法を使う手法を紹介します。

ユークリッドの互除法とは数$a$, $b$が与えられたときにその最大公約数を求める手法ですが、その解を求める課程を利用して

\[ax + by = 1 \]

を解くことができるのです。実際ここで $a=N, b=n$として両辺をNで割ったあまりをみれば

\[by = 1 \pmod N\]

ですからyが求めるものであることがわかります。ちなみに上の式は$a, b$が互いに素なら(つまりGCD(a,b)=1ならば必ず解を持つことが知られています。

さてそのアルゴリズムですが、このアルゴリズムをを一般式で書くと煩雑になるので具体的に $a = (N = )916132831, b = (n = ) 9973$ として説明します。 まず$a$を$b$で割った余りと商を利用して以下のように変形します。

\[ 916132831x + 9973y\\ = (91861\times 9973 + 3078)x + 9973y\\ = 3078x + 9973(91861x + y) \]

ここで \[ x' = 91861x + y\\ y' = x \] とすれば \[ 9973x' + 3078y' \] という式が得られます。商と余りを利用してより小さい係数の式を得ることができました。

定理

$a_1, b_1$を正の整数で$a_1 > b_1$とし$a_n, b_n, x_n, y_n$を以下のように定義する \[ a_{n+1} = b_n\\ b_{n+1} = m_n\\ x_{n+1} = d_n x_n + y_n\\ y_{n+1} = x_n \] ただし$d_n$は$m_n$は \[ a_n = d_n b_n + m_n (0 \le m_n < b_n) \] を満たす整数とすると$a_n > b_n$であり \[ a_1 x_1 + b_1 y_1 = a_n x_n + b_n y_n \] が成立する。

このように書くと何やら複雑ですがプログラム的には

a[n+1] = b[n]
b[n+1] = a[n] % b[n]

ということです。このように$a_n, b_n$だけを計算していくといつかは$a_n$は$1$に、$b_n$は0になります。そのとき

\[ x_n = 1\\ y_n = 0 \] とすると、 \[ a_n x_n + b_n y_n = 1 \] を満たしますから、 これから逆に、$x_{n-1}, y_{n-1}$が求まってゆき、最終的に$y_1$が求まります。 これが求める答えになります。 例として、$a_1=916132831$と$b_1=9973$で計算していくと以下のようになります。

         #         a         b         d         m
         1 916132831      9973     91861      3078
         2      9973      3078         3       739
         3      3078       739         4       122
         4       739       122         6         7
         5       122         7        17         3
         6         7         3         2         1
         7         3         1         3         0
         8         1         0

これから$x_8=1, y_8=0$が求まります。 これから$x_7, y_7, x_6, y_6, ...$と計算していくと

         #         x         y
         7         0         1
         6         1        -2
         5        -2        35
         4        35      -212
         3      -212       883
         2       883     -2861
         1     -2861 262815204

となり、$y_1 = 262815204$が求まります。

実際 $9973 \times 262815204 = 1 \pmod N$です。

サンプルコード


#!/usr/bin/env ruby

a = []
b = []
d = []
m = []
x = []
y = []
n = a[1] = 916132831
b[1] = 9973

i = 1
while b[i] != 0
  d[i] = a[i] / b[i]
  m[i] = a[i] % b[i]

  a[i + 1] = b[i]
  b[i + 1] = m[i]
  
  i = i + 1
end

x[i] = 1
y[i] = 0
j = i
while j > 1
  j = j - 1
  x[j] = y[j + 1]
  y[j] = x[j + 1] - d[j] * x[j]
end

puts("#{y[1]} * #{b[1]} = #{b[1] * y[1] % n} (mod #{n})") 

ユークリッドの互除法はとても早く1まで係数が降下するので効率もよいのですが$a_n, b_n$の途中の計算結果を保存しておかないといけないという問題があります。また、$d, m$を求めるのに商計算をしなくてはなりません。 一般的に商の計算はとても遅く、特にNが数1000bitともなるとその計算がオーバヘッドとなるので、出来ることなら使いたくないというのが本音です。そこでより効率のよいアルゴリズムがopensslでは使われています。それを次回に紹介したいと思います。

Posted by issei

カテゴリ: 数学

半径1の円に内接する正N角形の一辺の長さ

三角関数使って表記すれば半径1の円に内接する正N角形の一辺の長さは

\[2\sin(\pi/N)\]

なんですが、この値は具体的に加減乗除と累乗根を使って表すことができます。 それを計算してみようという試み。

正三角形

\[2\sin(\pi/3) = \sqrt{3}\]

正方形

\[2\sin(\pi/4) = \sqrt{2}\]

正6角形

\[2\sin(\pi/6) = 1\]

ここまでは図を書けば殆ど自明です。正8角形、正12角形は半角の公式を使うと比較的簡単に求まります。半角の公式とは

\[\sin^2(\alpha/2) = \frac{1−\cos\alpha}{2}\]

です。

正8角形

\begin{eqnarray*} 2\sin(\pi/8) = 2\sqrt{\frac{1-\cos(\pi/4)}{2}}\\ = \sqrt{2-\sqrt{2}} \end{eqnarray*}

正12角形

\begin{eqnarray*} 2\sin(\pi/12) = 2\sqrt{\frac{1-\cos(\pi/6)}{2}}\\ = \sqrt{2-\sqrt{3}} \end{eqnarray*}

根号の中に根号になりますね。この先、16, 32, 64または24, 48, ..と増えていっても、半角の公式でどんどん数が求まっていきます。もちろん増える度に根号は深くなります、こんな風に辺の数が増えていくと、根号がどんどん深くなると予想されるのですが、正10角形は比較的シンプルな値になります。

正10角形

\[2\sin(\pi/10) = \frac{-1+\sqrt{5}}{2}\]

となります。正5角形よりシンプル。 実は正10角形は正5角形の作図がどうやって行われるかが理解できていると簡単に求めることができます。

circle97.png

一般に$x^n-1$の根を複素平面にプロットすると単位円に内接する正n角形の頂点となります。正10角形をプロットすると図のようになり、 一辺の長さは図の$P_1Q$になりますが、 これが$P_1+P_4$と原点Oからの距離($|P_1+P_4|$)に等しいことが見て取れると思います。

$P_1, P_2, P_3, P_4$は正5角形の頂点、すなわち$x^5-1$の根です。これには1という自明な根があるので因数分解ができて、

\[ x^5-1 = (x-1)(x^4+x^3+x^2+x+1) \]

この第2項

\begin{eqnarray} x^4+x^3+x^2+x+1 \hbox{  (★)} \end{eqnarray}

の根ということになります。その根の1つを$\zeta$とすれば、すべての根は

\[ \zeta, \zeta^2, \zeta^3, \zeta^4 \]

となります。また$\zeta$は★の根ですから$\zeta+\zeta^2+\zeta^3+\zeta^4 = -1$になります。 ここでは$P_1=\zeta$とします。 今

\begin{eqnarray*} X = \zeta + \zeta^4\\ Y = \zeta^2 + \zeta^3 \end{eqnarray*}

とすれば

\begin{eqnarray*} X+Y = \zeta+\zeta^2+\zeta^3+\zeta^4 = -1\\ XY = \zeta+\zeta^2+\zeta^3+\zeta^4 = -1 \end{eqnarray*}

ですから($\zeta^5 = 1$に注意)X, Yは

\[ x^2 + x - 1 \]

の根。よって

\[ X = \frac{-1 + \sqrt{5}}{2} \]

となります。Xが$P_1+P_4$なのは言わずもがなです。これから次の有名な問題を証明できます。

問題)円周率が3.05より大きいことを証明せよ

\[ 2\pi > 10 \times \frac{-1 + \sqrt{5}}{2} = 6.180... > 6.1 \]

模範解答では、正8角形や正12角形を使うものが多いわけですが、こちらの方がより根号の数が少なく計算が簡単ですね。$\sqrt{5}=2.236...$というのを知っていればいいわけで。

なお余談ながら

\[1: |P_2+P_3|\] \[|P_1+P_4|:1\]

はいわゆる黄金比(1:1.618....)です。こんな計算のやりかたを知らなくても正10角形には黄金比が隠れていることを知っていれば3.05より大きいのは直ぐにわかるでしょう。いきなり正10角形の辺の長さは黄金比1.618:1だから・・・と書き始めたら正解になるかどうかはわかりませんが。

Posted by issei

カテゴリ: 数学

せっかくなので正17角形の計算式乗せとこ

Texの文章そのままコピペでいいのは楽ですね。コミケのときに書いた原稿をそのままコピペ。

\[ \alpha_{0} = \left(-1 + \sqrt{17}\right)/2 \] \[ \alpha_{1} = \left(-1 - \sqrt{17}\right)/2 \] \[ \beta_{0} = \left(\alpha_{0} + \sqrt{\alpha_{0}^2 +4}\right)/2 \] \[ \beta_{1} = \left(\alpha_{1} + \sqrt{\alpha_{1}^2 +4}\right)/2 \] \[ \gamma_{0} = \left(\beta_{0} + \sqrt{\beta_{0}^2 - 4\beta_{1}}\right)/2 \] \[ \delta_{0} = \left(\gamma_{0} + \sqrt{\gamma_{0}^2 - 4}\right)/2 \] \[ \delta_{0}^{17} = 1 \]

ちなみに、ためしに正65537角形の式を載せたらブラウザ固まりました(式長すぎたか?)

Posted by issei

カテゴリ: 数学

MathJaxを使ってみる


Tex形式で数式を書けばJavaScriptが勝手に数式をほげほげして見やすい形式に変更してくれるというシステム"MathJax" 数式をWebに書きたいという要求は凄いな。 一瞬Texのソースが見えるのがアレですけど。

ただこれちょっとシステムが複雑すぎませんかね?複雑・多機能なシステムは更新が大変。最低限要求されていることはもっとシンプルな気がする。

\[\int_a^b f(x) dx=F(b)-F(a)\]

\[\mathbf{V}_1 \times \mathbf{V}_2 = \begin{vmatrix} \mathbf{i} & \mathbf{j} & \mathbf{k} \\ \frac{\partial X}{\partial u} & \frac{\partial Y}{\partial u} & 0 \\ \frac{\partial X}{\partial v} & \frac{\partial Y}{\partial v} & 0 \end{vmatrix} \]

参考までに、同じものをmimetexで書くとこんな感じになります。 見た目は圧倒的にMathJaxのほうがよいですね。


Posted by issei

カテゴリ: 数学

自分メモ2

8k+1型の素数Pは x^2 + 2y^2 = P と表すことができる。これを計算する方法の自分メモ(および考察)

例)
19 = 4^2 + 2*1^2
193 = 11^2 + 2*6^2


これも3k+1型同様な方法で計算できます。

x^2 + 2 = n*P、すなわち x^2 = -2 (mod P) をまず解くところから。

すなわち、有限体Fpにて x^2 = -2の根をもとめることになります。

以下 N=P-1とします。

ところで 4k+1型の素数には自乗して-1になる数があります。 それは原始根をeとすれば、e^(N/4) に相当するのでした。 8k+1も4k+1型ですから、当然そういう数があります。

その数を iと置けば

(1+i)^2 = 2i

うーん。惜しい。右辺のiが邪魔ですね。しかしNは8の倍数ですから、 自乗して iになる数、すなわち8乗して1になる数があります。それは e^(N/8)のような数です。 この数をjとすれば

(j+ij)^2 = 2ijj = -2

これが答えです。 左辺を実際に計算すると

j = e^(N/8)
ij = e^(3N/8)

ということになります。

例) 193の原始根は5である。N=192だから、N/8は24, 3N/8は72

5^24 = 43 5^72 = 184

故に 43+184=23=34 (mod 192)

が答え。実際

34^2+2 = 1185 = 11 * 193

あとは、前回同様 K(√-2)を考えて、その中で素因数分解をしていく わけですが、ここで右辺に11がでてきました。

これは8k+1型ではありません。困りました。

実は 8k+3型の素数も x^2 + 2y^2 = P と表すことができるのです。 実際11は 3^2+2 と表せるので、K(√-2)では既約ではありません。

が、ここで、説明したような8k+1型のやり方ではどうやっても答えを求めることができません。

そこで、次のようにします。

Fpでは数 x は (P-1)/2乗すると-1になります。 したがって、さらに1乗、すなわち(P+1)/2乗すると、-xになります。

これを利用します。

今 x^2 = -2 (mod P)に解があるとします(※)。両辺を (P+1)/4乗すると

x^((P+1)/2) = (-2)^((P+1)/4)

-x = (-2)^((P+1)/4)

x = -(-2)^((P+1)/4)

これが答えです。

4k+3型の素数Pに関しては P+1が4の倍数になるので、こういう技が使えるわけです。

例) P=11とします。

x^2 = -2 (mod 11)

両辺を3乗して

x^6 = -x = -8 (mod 11)

故に x= 8。

実際、8^2+2 = 66

で、最後に(※)ですが、これは平方剰余の相互法則で解があるかどうかがわかります。 解がある条件は

p=8k+1, 8k+3

となります。

で、これだけでは何ですので、もうちょっと考察を。

P=4k+3

とするとこのFpには-1の平方根がありません。そこでそういう数があるとして、iとおきましょう。

すると、a + bi (a, bはFpの元)というものが考えられます。これはP^2個の元からなります。P^2 = Qとおきます。

ところで、このような数は加減乗除に関して閉じており体になります。0を覗くQ-1個の元に関しては、Q-1乗して初めて1となる数、すなわち原始根を持っています。 (何故そうなるのかと言えば、多項式環 Fp[X]の x^2+1による剰余環が聖域だから)

例)P=11とする。Q=121である。e = (1+4i)とすれば

e^2 = (7+8i), e^3 = (8+3i), .... e^120 = 1

120乗して初めて1になるのでeは原始根。

ところで、奇素数Pにおける、Q-1は必ず8の倍数になるので、 このような体Fqでは1の8乗根があります。

その中でも8乗しないと1にならない数が4つあり、 それは指数が、(Q-1)/8, 3(Q-1)/8, 5(Q-1)/8, 7(Q-1)/8 となるところで、例えばP=11なら

e^15, e^45, e^75, e^105 です。

今e^15をjとおけば、j^3, j^5, j^7が8乗根となります。

実際計算してみると、

j= e^15 = 4+7i
j^3 = e^45 = 4+4i
j^5 = e^75 = 7+4i
j^7 = e^105 = 7+7i


ところで

e^120 = 1
e^60 = -1
e^30 = i


だから、

e^15 = jとすれば ij = e^45

故に (e^15 + e^45)^2 = 8^2 = -2(mod 11)

となるわけです。見れば分かる通り、和を取るとiの係数が0になるのが味噌で、iの係数が0 というのは、つまりその数がFpの元になるということ。

このようにe^15 と e^45が共役だから綺麗に消えてくれるわけですが、 どんな奇素数でも共役になるというわけではありません。

ところで、Fqにはフロベニウス写像というのがあります。簡単に言うと

Fqにおいて、元をp乗すると、必ずその共役元になる

というものです。実際 e^15の 11乗を考えれば、

(e^15)^11 = e^165 = e^45

(e^120=1だから)

さらに考察すれば j=e^15は 8乗根なわけだから、8乗すると1になってしまうわけで、 となると、jをP乗するときは、Pを8で割った余りが重要になります。

もしPを8で割ったあまりが3ならばフロベニウス写像により、jは j^3に移されます。 あまりが7ならば j^7に移されます。

11は 8k+3型ですから、 j^3 すなわち ijが共役元であり、(j+ij)^2が2となります。

一方 8k+7型は、 j^7すなわち -ijが共役元ですから、(j-ij)がFpの元になることがわかります。実際その平方を計算すると

(j-ij)^2 = 2

となります。よって、8k+7型の素数では

平方して 2 となる元があることがわかります。 実際

3^2 = 2 (mod 7)

なるほど、こう考えると平方剰余の相互法則もまた違った視点で見えてくるな。 と思った次第。

続く(予定)
Posted by issei

カテゴリ: 数学

自分メモ

ひらめいたのでメモしておく。

3n+1型の素数Pは x^2 + 3y^2 = P と表すことができる。 その証明は代数学の環論でされるわけですが、数学者というのは証明しちゃったあと 具体的にそれを求めるアルゴリズムをちゃんと説明してくれないから困るわけで。

このやり方をずーっと考えていました。

自明なやり方は1..P-1までの数全てについて、試してみる。所詮数は有限だ。 しかし、これは、Pが大きくなると数が多くなり結構大変です。

オイラが出した手法は次の通り。

step 1) x^2 + 3 = 0 ( mod p)

の解を解く。つまり x^2 + 3 がpで割り切れるのだから、x^2 + 3 = npである。(nは整数)

step 2) step1の式は

x^2 + 3y^2 = np でy = 1としたものである。ここから、頑張ってより小さい x, y, nを探してゆき、最終的に nを1にする。

この二本立て。

さて、アルゴリズム的には STEP2のほうがすぐ思い付いた。

これは二次体の整数 K(√-3)を考えれよい。この世界では左辺は

(x-y√-3)(x+y√-3) = np と因数分解できる。

左辺は共役でn, pで割り切れないから、右辺のnもpも共役な積に分解されるはずである。

ここで証明をはしょって結論だけかけば、nは 3n+1の形の素数((a-b√-3)(a+b√-3)と分解可)、3(=√-3*√-3)、4(=(1+√-3)(1-√-3))、の積である。

故にこれらの因数で左辺の2項のどちらかが割り切れる。 (例えばnが素因数として 4を含むなら (x-y√-3), (x+y√-3)のどちらかが(1+√-3)で割り切れるはずだ。

このようにして、どんどん分解していけば最終的に求める式が求まる。

で、問題のSTEP1ですが、こちらはこうやる

x^2 = -3 ( mod p)

を求める。

ところで、 3n+1の素数Pの原始根をeとすれば n=P-1乗すると1になるのだが、これは3で割り切れるから、mod Pでは1の三乗根がある。これらの数は nを三等分したところ、すなわち

e^(n/3)

e^(2n/3)

である。これをωとω^2とおけば

ω + ω^2 = -1

に注意してその差の自乗を計算すると

(ω - ω^2)^2 = (ω^2 + ω - 2ω^3) = -3

故にω - ω^2 が答えである。

(ω - ω^2)^2はいわゆる判別式。

ω + ω^2 = -1となるのは

ωはx^3 - 1の根であり、自明な根1をくりだしてやれば

x^3 - 1 = (x-1)(x^2 + x + 1)

第二項が0になるはずだからω^2 + ω +1 = 0

このあたり円分多項式とかなり関連があるわけで、 このようにリンクするのがまた面白い。

例 素数2011を考える。原始根は3である

ω= 3^670 = 205 ω^2 = 3^1340 = 1805

故にその差 1600 = -411 (mod 2011)がSTEP1の解。実際

411^2 + 3 = 84 * 2011

である。 84は 4*3*7と因数分解できる。7は3n+1型だから、(x+y√-3)(x-y√-3)の形に 表せる。4も3も同様。実際に割って行くと

44^2 + 3*5^2 == 2011

を得る。
Posted by issei

カテゴリ: 数学