<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>数学・暗号・量子 on kenji.blog</title><link>http://kenji.blog/categories/%E6%95%B0%E5%AD%A6%E6%9A%97%E5%8F%B7%E9%87%8F%E5%AD%90/</link><description>Recent content in 数学・暗号・量子 on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>ja</language><copyright>kenjinote</copyright><lastBuildDate>Sat, 05 Sep 2026 22:10:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/categories/%E6%95%B0%E5%AD%A6%E6%9A%97%E5%8F%B7%E9%87%8F%E5%AD%90/index.xml" rel="self" type="application/rss+xml"/><item><title>【完全解剖】量子コンピュータとは何か？〜ゼロからわかる究極の計算原理〜</title><link>http://kenji.blog/p/quantum-computer-basics/</link><pubDate>Sat, 05 Sep 2026 22:10:00 +0900</pubDate><guid>http://kenji.blog/p/quantum-computer-basics/</guid><description>&lt;img src="http://kenji.blog/p/quantum-computer-basics/quantum_basics_eyecatch_1788613712487.jpg" alt="Featured image of post 【完全解剖】量子コンピュータとは何か？〜ゼロからわかる究極の計算原理〜" />&lt;h2 id="はじめに量子コンピュータがもたらす計算のパラダイムシフト">はじめに：量子コンピュータがもたらす「計算のパラダイムシフト」
&lt;/h2>&lt;p>近年、ニュースや技術記事で「量子コンピュータ」という言葉を目にしない日はありません。「現在のスーパーコンピュータで何千年もかかる計算を数分で終わらせる」「現在の暗号技術がすべて破られるかもしれない」といった、SF映画のような話がまことしやかに語られています。GoogleやIBM、Microsoftといった巨大IT企業から、世界中の大学やスタートアップ企業までが、この夢の技術の実用化に向けてしのぎを削っています。&lt;/p>
&lt;p>しかし、「量子コンピュータとは結局のところ何なのか？」と問われると、正確に答えられる人は少ないのではないでしょうか。多くの人が「すべての組み合わせを同時に計算できる魔法の箱」といった漠然としたイメージを持っていますが、厳密にはそれは正しくありません。&lt;/p>
&lt;p>本記事では、量子コンピュータが古典コンピュータ（私たちが普段使っているPCやスマートフォン）と根本的にどう違うのか、そして「重ね合わせ（Superposition）」「量子もつれ（Entanglement）」「量子ゲート（Quantum gates）」といった量子力学の不思議な現象をどのように計算に利用しているのかを、基礎から徹底的に、かつ専門的でありながらわかりやすく解説します。この記事を読み終える頃には、量子コンピュータの本質的な凄さと、現在の課題がはっきりと理解できるはずです。&lt;/p>
&lt;hr>
&lt;h2 id="第1章古典コンピュータと量子コンピュータの決定的な違い">第1章：古典コンピュータと量子コンピュータの決定的な違い
&lt;/h2>&lt;p>量子コンピュータの仕組みを理解するためには、まず私たちが現在使っている「古典コンピュータ」がどのように動いているかをおさらいする必要があります。&lt;/p>
&lt;h3 id="比較表古典コンピュータ-vs-量子コンピュータ">比較表：古典コンピュータ vs 量子コンピュータ
&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>項目&lt;/th>
&lt;th>古典コンピュータ&lt;/th>
&lt;th>量子コンピュータ&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>基本単位&lt;/strong>&lt;/td>
&lt;td>ビット (0 または 1)&lt;/td>
&lt;td>量子ビット (0と1の重ね合わせ)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>状態の表現&lt;/strong>&lt;/td>
&lt;td>確定的&lt;/td>
&lt;td>確率的（観測するまで決定しない）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>計算方式&lt;/strong>&lt;/td>
&lt;td>逐次処理（並列化には物理コアが必要）&lt;/td>
&lt;td>量子並列性（指数関数的な状態を同時に操作）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>得意な計算&lt;/strong>&lt;/td>
&lt;td>四則演算、日常的なデータ処理&lt;/td>
&lt;td>素因数分解、量子化学計算&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>エラー耐性&lt;/strong>&lt;/td>
&lt;td>非常に強い&lt;/td>
&lt;td>非常に弱い（極低温環境や誤り訂正が必要）&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="古典コンピュータの世界0か1かのビットbit">古典コンピュータの世界：0か1かの「ビット（Bit）」
&lt;/h3>&lt;p>古典コンピュータは、すべての情報を「0」か「1」のどちらかの状態で表現します。これを &lt;strong>ビット（Bit）&lt;/strong> と呼びます。物理的には、半導体チップ上のトランジスタの電圧が高い（1）か低い（0）かで表現されます。
あなたのスマートフォンに入っている高画質な写真も、今読んでいるこの文章も、お気に入りのYouTubeの動画も、究極的には膨大な数の「0と1の羅列」に還元されます。計算とは、この0と1の羅列に対して、AND（論理積）、OR（論理和）、NOT（論理否定）といった基本的な論理回路を組み合わせて操作を加えるプロセスに他なりません。
これは非常に確実で決定論的な世界です。入力が同じであれば、必ず同じ出力が得られます。&lt;/p>
&lt;h3 id="量子コンピュータの世界0であり1でもある量子ビットqubit">量子コンピュータの世界：0であり1でもある「量子ビット（Qubit）」
&lt;/h3>&lt;p>一方、量子コンピュータの最小情報単位は &lt;strong>量子ビット（Qubit：Quantum bit）&lt;/strong> と呼ばれます。
量子ビットの最大の特徴は、古典的なビットのように「0」か「1」のどちらか一方の状態にあるだけでなく、「0と1が特定の確率で混ざり合った状態」をとることができる点にあります。これを &lt;strong>「重ね合わせ（Superposition）」&lt;/strong> と呼びます。&lt;/p>
&lt;p>例えば、古典ビットが「表」か「裏」のどちらかを上にして置かれたコインだとすると、量子ビットは「空中で回転し続けているコイン」によく例えられます。回転中のコインは表とも裏とも言えず、両方の状態が重なり合っています。そして、コインが床に落ちて動きを止めた瞬間（これを量子力学では「観測」と呼びます）、初めて「表」か「裏」かが確定します。&lt;/p>
&lt;p>この「観測するまで状態が確定しない」というミクロな世界（量子力学）特有の性質を、そのまま情報処理のプロセスに組み込んだのが量子コンピュータなのです。&lt;/p>
&lt;hr>
&lt;h2 id="第2章計算を根本から変える3つの量子力学的性質">第2章：計算を根本から変える3つの量子力学的性質
&lt;/h2>&lt;p>量子コンピュータの驚異的な計算能力の源泉は、単にクロック周波数が高いとか、部品が小さいといったことではありません。物理法則そのものを計算のリソースとして利用する点にあります。主に以下の3つの量子力学的な現象が鍵となります。&lt;/p>
&lt;h3 id="1-重ね合わせsuperpositionと指数関数的な情報量">1. 重ね合わせ（Superposition）と指数関数的な情報量
&lt;/h3>&lt;p>先述の通り、量子ビットは0と1の両方の状態を同時に保持することができます。1つの量子ビットは「0と1の重ね合わせ」ですが、量子ビットの数を増やすとどうなるでしょうか。&lt;/p>
&lt;ul>
&lt;li>1量子ビット：2つの状態（0, 1）の重ね合わせ&lt;/li>
&lt;li>2量子ビット：4つの状態（00, 01, 10, 11）の重ね合わせ&lt;/li>
&lt;li>3量子ビット：8つの状態の重ね合わせ&lt;/li>
&lt;li>&lt;strong>N個の量子ビット：$2^N$個のパターンの重ね合わせ&lt;/strong>&lt;/li>
&lt;/ul>
&lt;p>たった50個の量子ビットがあれば、$2^{50}$（約1100兆）個の状態を同時に保持できます。そしてわずか300個の量子ビットがあれば、$2^{300}$個（宇宙に存在する全原子の数よりも多い数！）のパターンを一度に保持することができるのです。この指数関数的な情報保持能力が、量子コンピュータのポテンシャルの土台となっています。古典コンピュータで宇宙の原子の数よりも多い状態をメモリに記憶させることは、物理的に不可能です。&lt;/p>
&lt;h3 id="2-量子もつれentanglement不気味な遠隔作用">2. 量子もつれ（Entanglement）：不気味な遠隔作用
&lt;/h3>&lt;p>量子もつれは、アインシュタインが「不気味な遠隔作用（Spooky action at a distance）」と呼んで生涯受け入れられなかったほど、人間の直感に反する不思議な現象です。&lt;/p>
&lt;p>複数の量子ビットが「量子もつれ」の状態になると、それらは互いに強く結びつき、 &lt;strong>「片方の状態が確定すると、どれだけ距離が離れていても、もう片方の状態が瞬時に確定する」&lt;/strong> という運命共同体のような関係になります。&lt;/p>
&lt;p>例えば、もつれ状態にある2つの量子ビットAとBがあるとします（これらはそれぞれ0と1の重ね合わせ状態にあります）。Aを観測して「0」だった場合、情報の伝達速度の限界である光の速さを超えて、瞬時にBの状態も（例えば必ず「1」になるように）確定します。
量子コンピュータでは、この量子もつれを利用することで、複数の量子ビット同士の複雑な相関関係を表現し、超並列的な情報処理を行います。もつれがなければ、量子コンピュータの計算能力は古典コンピュータと大差ないものになってしまいます。&lt;/p>
&lt;h3 id="3-量子干渉quantum-interference正解を浮かび上がらせる魔法">3. 量子干渉（Quantum Interference）：正解を浮かび上がらせる魔法
&lt;/h3>&lt;p>「すべてのパターンを同時に保持できるなら、それを一気に並列計算して一瞬で答えが出るのでは？」と思うかもしれません。これが、量子コンピュータに対する最もよくある誤解です。
重ね合わせ状態で計算を行っても、最終的に答えを知るためには「観測」しなければなりません。しかし観測した瞬間、状態は$2^N$個のパターンのうちのどれか1つにランダムに収縮してしまいます。これでは、単にでたらめな（ランダムな）答えが出てくるだけです。&lt;/p>
&lt;p>ここで登場するのが &lt;strong>「量子干渉（Interference）」&lt;/strong> です。波と波がぶつかると、波長が合うところは強め合い、ズレているところは打ち消し合う現象を利用します（ノイズキャンセリングイヤホンの原理と本質的には同じです）。&lt;/p>
&lt;p>優れた「量子アルゴリズム」は、計算の過程で &lt;strong>「正解につながる状態（波）の確率振幅を強め合い（増幅）」「不正解につながる状態の確率振幅を打ち消し合う（相殺）」&lt;/strong> ように、巧みに量子状態を操作します。そして最終的に観測したときに、限りなく100%に近い確率で「正解」がポロッと出てくるように仕向けるのです。この干渉のプロセスをうまく設計することこそが、量子プログラミングの真髄です。&lt;/p>
&lt;hr>
&lt;h2 id="第3章どのように計算するのか量子ゲートと量子回路">第3章：どのように計算するのか？「量子ゲート」と「量子回路」
&lt;/h2>&lt;p>古典コンピュータが論理ゲート（AND、OR、NOTなど）を使って計算を進めるように、量子コンピュータも &lt;strong>「量子ゲート（Quantum Gates）」&lt;/strong> と呼ばれる操作を量子ビットに適用して計算を進めます。複数の量子ゲートを組み合わせたものを ** 量子回路（Quantum Circuit）** と呼びます。&lt;/p>
&lt;p>量子ビットの状態は、「ブロッホ球（Bloch sphere）」という3次元の球体の表面上の点として数学的に表現されます。北極が「0」、南極が「1」、赤道上が「0と1が半々に重なり合った状態」です。量子ゲートとは、この球の表面で状態（ベクトル）を回転させる操作に他なりません。&lt;/p>
&lt;p>代表的な量子ゲートをいくつか紹介しましょう。&lt;/p>
&lt;h3 id="1-アダマールゲートhゲート">1. アダマールゲート（Hゲート）
&lt;/h3>&lt;p>古典コンピュータには存在しない、量子コンピュータならではの最も基本的なゲートです。状態が完全に「0」の量子ビットにHゲートを通すと、0と1がちょうど半分ずつの確率で観測される「完全な重ね合わせ状態」（ブロッホ球でいう赤道上の点）を作り出します。量子計算の初期化ステップとして、多くのアルゴリズムがまずこのHゲートをすべての量子ビットに適用することから始まります。&lt;/p>
&lt;h3 id="2-パウリゲートx-y-zゲート">2. パウリゲート（X, Y, Zゲート）
&lt;/h3>&lt;p>古典コンピュータのNOTゲート（0を1に、1を0に反転させる）に相当する操作を含むゲートです。ブロッホ球において、X軸、Y軸、Z軸を中心に180度回転させる操作に相当します。特にXゲートは、北極（0）を南極（1）に反転させるため、古典のNOTゲートと全く同じ働きをします。Zゲートは、重ね合わせの「位相（波のタイミングのようなもの）」を反転させる役割を持ち、量子干渉を起こす上で極めて重要です。&lt;/p>
&lt;h3 id="3-cnotゲート制御notゲート">3. CNOTゲート（制御NOTゲート）
&lt;/h3>&lt;p>量子もつれを作り出すための超重要ゲートです。2つの量子ビット（制御ビットと標的ビット）を使います。
「もし制御ビットが1ならば、標的ビットの状態を反転（Xゲート）させる。制御ビットが0ならば何もしない」という動作をします。一見単純なIF条件分岐に見えますが、制御ビットが「0と1の重ね合わせ状態」だった場合どうなるでしょうか？ 標的ビットは「反転したものと反転しないものが重なり合った状態」になり、2つのビットの運命が完全にリンクします。見事に2つの量子ビットが「もつれ」るのです。&lt;/p>
&lt;p>これらのゲートを音楽の楽譜のように左から右へ順番に配置・適用していくことで、複雑なアルゴリズムを実行します。&lt;/p>
&lt;hr>
&lt;h2 id="第4章量子コンピュータは何が得意で何が苦手なのか">第4章：量子コンピュータは何が得意で、何が苦手なのか？
&lt;/h2>&lt;p>ここで重要な事実をお伝えします。量子コンピュータは、万能の神ではありません。
ウェブブラウジング、動画のレンダリング、エクセルのマクロ処理、あるいは一般的なスマホアプリの動作といった日常的なタスクにおいて、量子コンピュータが古典コンピュータを凌駕することはおそらく永遠にないでしょう。これらの逐次的な処理は、すでに高度に最適化され、圧倒的な速度と安価さを誇る古典コンピュータのほうが適しています。&lt;/p>
&lt;p>量子コンピュータがその真価を発揮するのは、 &lt;strong>「古典コンピュータでは計算の組み合わせが指数関数的に爆発してしまい、宇宙の寿命ほどの時間がかかってしまう特定の問題」&lt;/strong> に対してのみです。これを「量子超越性（Quantum Supremacy）」または「量子優位性（Quantum Advantage）」と呼びます。&lt;/p>
&lt;h3 id="量子コンピュータが得意なことキラーアプリケーション">量子コンピュータが得意なこと（キラーアプリケーション）
&lt;/h3>&lt;h4 id="1-素因数分解と暗号解読ショアのアルゴリズム">1. 素因数分解と暗号解読（ショアのアルゴリズム）
&lt;/h4>&lt;p>現在、インターネット上の安全な通信（クレジットカードの決済や個人情報の送信など）を守っている「RSA暗号」などは、「巨大な数の素因数分解は古典コンピュータには実質的に不可能（膨大な時間がかかる）である」という前提に基づいています。
しかし、1994年に数学者ピーター・ショアが発見した「ショアのアルゴリズム」を使えば、量子コンピュータは干渉を巧みに利用して、これを劇的なスピード（多項式時間）で解くことができます。これにより、将来的に現在の暗号体系が崩壊するリスクがあり、世界中の中央銀行や政府機関が「耐量子暗号（Post-Quantum Cryptography）」への移行を急いでいます。&lt;/p>
&lt;h4 id="2-量子化学計算と新素材創薬開発">2. 量子化学計算と新素材・創薬開発
&lt;/h4>&lt;p>自然界の分子や原子の振る舞いは、そもそも量子力学の法則に従っています。古典コンピュータで複雑な分子の挙動をシミュレーションしようとすると、電子同士の相互作用の組み合わせが爆発し、比較的小さな分子でも計算量の限界にぶつかります。
ノーベル物理学賞受賞者のリチャード・ファインマンが「自然をシミュレートしたければ、量子力学的に作らなければならない」と語った通り、量子コンピュータは物質のシミュレーションにおいて圧倒的なネイティブパワーを発揮します。画期的な新薬の設計、常温超伝導物質の発見、高効率な太陽電池やバッテリー材料の開発、エネルギー効率の高い肥料の合成など、人類の課題を解決するブレイクスルーが期待されています。&lt;/p>
&lt;h4 id="3-組み合わせ最適化問題と探索グローバーのアルゴリズム">3. 組み合わせ最適化問題と探索（グローバーのアルゴリズム）
&lt;/h4>&lt;p>膨大な選択肢の中から最適なものを見つけ出す問題（物流の最適化ルート、金融ポートフォリオの最適化など）に対しても、量子アルゴリズムは力を発揮します。「グローバーのアルゴリズム」を使えば、データが未整理のデータベースからの検索において、古典コンピュータのルート（平方根）の回数で目的のデータを見つけ出すことができます。例えば、1億件のデータがあれば、古典で最大1億回かかる探索を、わずか1万回程度で完了できることになります。&lt;/p>
&lt;hr>
&lt;h2 id="第5章立ちはだかるハードウェアの壁デコヒーレンスと量子エラー訂正">第5章：立ちはだかるハードウェアの壁「デコヒーレンス」と「量子エラー訂正」
&lt;/h2>&lt;p>理論的には魔法のように強力な量子コンピュータですが、実用化への道のりには極めて高く険しい物理的な壁が立ちはだかっています。最大の敵は &lt;strong>「ノイズ」&lt;/strong> です。&lt;/p>
&lt;p>量子ビットの「重ね合わせ」や「量子もつれ」は、極めて繊細で壊れやすい状態です。周囲のわずかな熱、電磁波のゆらぎ、あるいは宇宙線などに触れただけで、その魔法の状態は一瞬で崩壊し、ただの古典ビットになってしまいます。この現象を &lt;strong>「デコヒーレンス（量子崩壊）」&lt;/strong> と呼びます。&lt;/p>
&lt;h3 id="物理的な実現方式の熾烈な競争">物理的な実現方式の熾烈な競争
&lt;/h3>&lt;p>現在、この繊細な量子ビットを物理的にどう作るかについて、世界中で様々な方式が研究されており、覇権争いが起きています。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>超伝導方式（Superconducting）&lt;/strong> ：Google、IBM、Amazonなどが採用。ループ状の超伝導回路を使用し、絶対零度（約-273℃）に近い極低温まで巨大な冷凍機で冷却して量子状態を制御します。現在最もリードし、量子ビット数を増やしやすい方式ですが、冷却装置が巨大で高価です。&lt;/li>
&lt;li>&lt;strong>イオントラップ方式（Trapped Ion）&lt;/strong> ：IonQ、Quantinuumなどが採用。真空中にイオン（原子）を電磁場で閉じ込め、精密なレーザーを当てて制御します。すべての量子ビットが均一で、状態を長く維持できる（コヒーレンス時間が長い）のが強みですが、操作速度が超伝導に比べて遅いという課題があります。&lt;/li>
&lt;li>&lt;strong>光量子方式（Photonic）&lt;/strong> ：PsiQuantumなどが注力。光の粒子（光子）を使います。極低温の環境を必要とせず室温で動作する部分が多く、既存のシリコンチップ製造技術や光ファイバー通信技術と相性が良いという大きな利点があります。&lt;/li>
&lt;li>&lt;strong>トポロジカル方式（Topological）&lt;/strong> ：Microsoftが長年研究。エニオンと呼ばれる特殊な粒子のトポロジー（位相幾何学）的な性質を利用し、環境ノイズに対して根本的に強い（エラーが起きにくい）量子ビットを作ろうとする野心的なアプローチです。理論上は最強ですが、物理的な実現のハードルが最も高いとされています。&lt;/li>
&lt;/ul>
&lt;h3 id="究極の目標誤り耐性量子コンピュータftqcへの道">究極の目標「誤り耐性量子コンピュータ（FTQC）」への道
&lt;/h3>&lt;p>現在の古典コンピュータの世界にも計算エラー（宇宙線によるビット反転など）は存在しますが、「誤り訂正コード」によって完璧に修正されているため、私たちは一度もエラーを意識することなくスマホを使えています。量子コンピュータでも実用的な大規模計算を行うためには、同様の &lt;strong>「量子エラー訂正（Quantum Error Correction: QEC）」&lt;/strong> が不可欠です。&lt;/p>
&lt;p>しかし、量子状態は「観測すると壊れる」という性質があるため、エラーを確認するために中身を直接見る（観測する）ことができないという致命的なジレンマがあります。
これを回避するため、多数の不安定な「物理量子ビット」を巧みに組み合わせて、エラーを検知・修正できる1つの安定した「論理量子ビット」を構築する理論が確立されています（表面符号など）。
しかし、1つの論理量子ビットを作るために1000〜1万個もの物理量子ビットが必要になると言われています。何千という論理量子ビットを使ってショアのアルゴリズムなどを実行するには、全体で数百万から数千万個の物理量子ビットを持つ巨大なシステムが必要になります。&lt;/p>
&lt;p>現在私たちがいるのは、 &lt;strong>NISQ（Noisy Intermediate-Scale Quantum：ノイズあり中規模量子）&lt;/strong> デバイスの時代と呼ばれています。エラー訂正を持たず、数十〜数百量子ビットで動く過渡期的なマシンです。
究極の目標である、完全にエラー訂正が可能な &lt;strong>「誤り耐性量子コンピュータ（Fault-Tolerant Quantum Computer: FTQC）」&lt;/strong> の実現には、まだ10年〜数十年という長期的な研究開発が必要だと専門家たちは予測しています。&lt;/p>
&lt;hr>
&lt;h2 id="第6章量子コンピュータの歴史と未来展望">第6章：量子コンピュータの歴史と未来展望
&lt;/h2>&lt;p>最後に、量子コンピュータがどのように生まれ、今後どこへ向かうのかを俯瞰してみましょう。&lt;/p>
&lt;h3 id="理論の誕生から量子超越性の実証まで">理論の誕生から「量子超越性」の実証まで
&lt;/h3>&lt;ul>
&lt;li>&lt;strong>1980年代&lt;/strong> ：物理学者ポール・ベニオフやリチャード・ファインマンが、量子力学の原理を利用したコンピュータの概念を提唱。「自然をシミュレートするなら量子力学を使え」という言葉が発端となりました。&lt;/li>
&lt;li>&lt;strong>1994年&lt;/strong> ：ピーター・ショアが素因数分解の量子アルゴリズム（ショアのアルゴリズム）を発表。世界に衝撃を与え、莫大な研究資金が流れ込むきっかけになります。&lt;/li>
&lt;li>&lt;strong>1996年&lt;/strong> ：ロブ・グローバーがデータ検索を高速化するグローバーのアルゴリズムを発表。&lt;/li>
&lt;li>**2019年 ** ：歴史的なマイルストーン。Googleが53量子ビットの超伝導プロセッサ「Sycamore」を用いて、古典のスーパーコンピュータで1万年かかる（とされた）乱数生成の検証計算を約200秒で完了させたと発表。世界初の &lt;strong>「量子超越性（Quantum Supremacy）」&lt;/strong> の実証宣言として大きな話題を呼びました（後にIBMなどが古典スパコン側のアルゴリズムを改善し、数日で計算可能と反論するなどの熱い議論が交わされました）。&lt;/li>
&lt;li>&lt;strong>2023年以降&lt;/strong> ：IBMが1000量子ビットを超えるプロセッサ「Condor」を発表。また、ハーバード大学などが「論理量子ビット」の生成と操作に成功するなど、エラー訂正技術の初期の実証が次々と報告され始めています。&lt;/li>
&lt;/ul>
&lt;h3 id="次世代のテクノロジーに向けて">次世代のテクノロジーに向けて
&lt;/h3>&lt;p>量子コンピュータは、単なる「クロック数が速い次世代のCPU」ではありません。計算という行為そのものの概念を、ミクロの世界を支配する量子力学のルールで根本から書き換える、まさに情報科学におけるパラダイムシフトです。&lt;/p>
&lt;p>私たちが生きているうちに、ポケットに入る「パーソナル量子スマートフォン」を持つことはないでしょう（それは必要もありません）。しかし、AWSやAzureのようなクラウドネットワークの向こう側にある強大な量子データセンターが、ある日突然、不治の病の特効薬を発見したり、地球温暖化を解決する夢のクリーンエネルギー材料（例えば、常温で大気中の窒素からアンモニアを合成する触媒など）を弾き出したりする未来は、確実に近づいています。&lt;/p>
&lt;p>今はまだ、巨大な真空管の熱で部屋中が暑くなりながら、パンチカードで動いていた1940年代のエニアック（ENIAC）のような黎明期に相当します。しかし、世界中のトップレベルの研究者やエンジニアたちが知恵を絞り、日々技術的なブレイクスルーが報告されています。
この新しい「計算の夜明け」の進化の過程をリアルタイムで目撃できる私たちは、歴史上非常にエキサイティングな時代を生きていると言えるでしょう。&lt;/p>
&lt;p>量子の世界への扉は、まだ開かれたばかりです。今後の動向から目が離せません。&lt;/p>
&lt;hr>
&lt;p>&lt;em>この記事は量子コンピューティングの基本概念をビジネスパーソンや技術に興味を持つ一般の方向けにわかりやすく解説することを目的としています。厳密な数学的・物理学的な定義（ブラ・ケット記法や複素確率振幅の詳細など）からは一部簡略化している部分があることをご了承ください。&lt;/em>&lt;/p></description></item><item><title>【PQC】量子コンピュータ時代の次世代暗号「耐量子計算機暗号」の全貌</title><link>http://kenji.blog/p/post-quantum-cryptography/</link><pubDate>Sat, 05 Sep 2026 22:09:22 +0900</pubDate><guid>http://kenji.blog/p/post-quantum-cryptography/</guid><description>&lt;img src="http://kenji.blog/p/post-quantum-cryptography/post_quantum_cryptography_1788613735417.jpg" alt="Featured image of post 【PQC】量子コンピュータ時代の次世代暗号「耐量子計算機暗号」の全貌" />&lt;h2 id="はじめに量子コンピュータがもたらす暗号技術への脅威">はじめに：量子コンピュータがもたらす暗号技術への「脅威」
&lt;/h2>&lt;p>現在、私たちがインターネット上で日常的に行っている通信——オンラインバンキングでの決済、ウェブサイトの閲覧（HTTPS）、メッセージアプリでのやり取り、そしてブロックチェーンや暗号資産の取引に至るまで——それらの多くは「公開鍵暗号」と呼ばれる技術によって守られています。具体的には、RSA暗号や楕円曲線暗号（ECC）といったアルゴリズムが、現代のデジタル社会の信頼性を支える根幹となっています。&lt;/p>
&lt;p>これらの暗号方式は、「巨大な数の素因数分解」や「離散対数問題」といった、現在の古典的コンピュータ（スーパーコンピュータを含む）では解くのに天文学的な時間がかかる数学的難問を安全性の根拠としています。しかし、近年目覚ましい進歩を遂げている &lt;strong>「量子コンピュータ」&lt;/strong> が実用化されると、この前提が根本から覆されることになります。&lt;/p>
&lt;p>1994年にピーター・ショア（Peter Shor）が発表した「ショアのアルゴリズム」は、十分な性能を持つ量子コンピュータを用いれば、素因数分解や離散対数問題を極めて短時間で解けることを数学的に証明しました。これはつまり、現在のインターネットを保護している暗号通信が、将来的にすべて解読されてしまうリスク（Y2Q：Years to Quantum、または Q-Day と呼ばれる問題）を意味しています。&lt;/p>
&lt;p>さらに深刻なのは、「Harvest Now, Decrypt Later（今データを盗んで蓄積し、将来暗号が解けるようになったときに解読する）」という攻撃手法の存在です。国家の機密情報や企業の知的財産、個人の生体情報など、数十年にわたって機密性を保つ必要があるデータは、すでに現在、将来の解読を前提とした窃取の対象となっている可能性があります。&lt;/p>
&lt;p>この未曾有の危機に対応すべく、世界中の暗号学者や研究機関が総力を挙げて開発を進めているのが、量子コンピュータの攻撃に対しても安全性を保つことができる次世代の暗号技術、 &lt;strong>耐量子計算機暗号（PQC：Post-Quantum Cryptography）&lt;/strong> なのです。本記事では、PQCの基礎から、主要なアルゴリズムの仕組み、そして米国国立標準技術研究所（NIST）が進める世界的な標準化の最新動向までを詳しく解説します。&lt;/p>
&lt;hr>
&lt;h2 id="耐量子計算機暗号pqcとは何か">耐量子計算機暗号（PQC）とは何か？
&lt;/h2>&lt;p>耐量子計算機暗号（Post-Quantum Cryptography, PQC）とは、既存の古典的コンピュータ上でも動作し、かつ将来登場するであろう大規模な量子コンピュータによる攻撃（ショアのアルゴリズムなど）に対しても耐性を持つように設計された暗号アルゴリズムの総称です。&lt;/p>
&lt;p>よく混同されがちな技術に「量子暗号（Quantum Cryptography）」や「量子鍵配送（QKD）」がありますが、これらは全く別のアプローチです。量子暗号（QKD）は、量子力学の物理法則（観測すると状態が変化する性質など）を利用して、通信経路上での盗聴を物理的に不可能にするハードウェアベースの技術です。専用の光ファイバーや特殊な機器が必要であり、導入コストや距離の制限という課題があります。&lt;/p>
&lt;p>一方、 &lt;strong>PQCはあくまで「数学」をベースとしたソフトウェアベースの暗号技術&lt;/strong> です。そのため、既存のインターネットインフラ、サーバー、スマートフォン、ブラウザなどにソフトウェアのアップデートとして組み込むことが可能であり、現実社会への適用性が非常に高いのが特徴です。世界中のIT企業や政府機関は、現在使用しているRSAやECCをこのPQCに置き換える（移行する）ことを急務としています。&lt;/p>
&lt;hr>
&lt;h2 id="pqcを支える4つの主要な数学的アプローチ">PQCを支える4つの主要な数学的アプローチ
&lt;/h2>&lt;p>量子コンピュータを使っても効率的に解けない数学的難問（NP困難な問題など）をベースにして、様々なPQCのアルゴリズムが提案されています。ここでは、現在主流となっている主要な4つのカテゴリーを紹介します。&lt;/p>
&lt;h3 id="耐量子計算機暗号pqcの主要なアプローチ">耐量子計算機暗号（PQC）の主要なアプローチ
&lt;/h3>&lt;p>`mermaid
graph LR
PQC[耐量子計算機暗号 PQC] &amp;ndash;&amp;gt; L[格子暗号 Lattice-based]
PQC &amp;ndash;&amp;gt; H[ハッシュベース暗号 Hash-based]
PQC &amp;ndash;&amp;gt; M[多変数多項式暗号 Multivariate]
PQC &amp;ndash;&amp;gt; C[符号ベース暗号 Code-based]&lt;/p>
&lt;pre>&lt;code>L --&amp;gt; L1(FIPS 203: ML-KEM)
L --&amp;gt; L2(FIPS 204: ML-DSA)
H --&amp;gt; H1(FIPS 205: SLH-DSA)
style PQC fill:#f9f,stroke:#333,stroke-width:2px
&lt;/code>&lt;/pre>
&lt;p>`&lt;/p>
&lt;h3 id="1-格子ベース暗号lattice-based-cryptography">1. 格子ベース暗号（Lattice-based Cryptography）
&lt;/h3>&lt;p>現在、PQCの分野で最も有望視され、主流となっているのがこの「格子暗号」です。格子暗号は、多次元空間上の規則正しく並んだ点（格子点）に関する問題を安全性の根拠としています。有名な問題としては、「最短ベクトル問題（SVP：Shortest Vector Problem）」や「LWE問題（Learning With Errors）」などがあります。&lt;/p>
&lt;p>&lt;strong>仕組みの概要：&lt;/strong>
非常に次元の高い（数百〜数千次元）空間内に無数の点が格子状に並んでいると想像してください。ある特定の格子点を見つけるのは、2次元や3次元なら簡単ですが、数百次元になると古典コンピュータでも量子コンピュータでも効率的に見つけ出すアルゴリズムは発見されていません。特にLWE問題は、「連立一次方程式に意図的に小さな『ノイズ（誤差）』を加えると、元の変数を推測するのが劇的に難しくなる」という性質を利用しています。&lt;/p>
&lt;p>&lt;strong>長所：&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>鍵共有（KEM）とデジタル署名の両方に適用可能。&lt;/li>
&lt;li>処理速度が非常に高速（RSAやECCよりも速い場合もある）。&lt;/li>
&lt;li>鍵のサイズや暗号文のサイズが比較的小さく、バランスが良い。&lt;/li>
&lt;/ul>
&lt;p>現在NISTが標準化しているアルゴリズムの多く（ML-KEMやML-DSAなど）が、この格子ベース暗号を採用しています。&lt;/p>
&lt;h3 id="2-ハッシュベース暗号hash-based-cryptography">2. ハッシュベース暗号（Hash-based Cryptography）
&lt;/h3>&lt;p>ハッシュベース暗号は、デジタル署名に特化したPQCアルゴリズムです。安全性の根拠は、SHA-2やSHA-3といった安全な「暗号学的ハッシュ関数」が持つ衝突耐性や一方向性にのみ依存しています。&lt;/p>
&lt;p>&lt;strong>仕組みの概要：&lt;/strong>
「ランポート署名（Lamport Signature）」と呼ばれる、1回しか使えない使い捨ての署名方式（ワンタイム署名）を出発点とします。これを「マークルツリー（Merkle Tree）」と呼ばれる木構造のデータ形式で束ねることで、1つの鍵ペアで複数回の署名を可能にしています。&lt;/p>
&lt;p>&lt;strong>長所：&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>セキュリティの根拠が極めて堅牢であり、「ハッシュ関数が安全である限り安全」という強い証明がある。&lt;/li>
&lt;li>数学的構造への依存が少ないため、予期せぬ解読法が見つかるリスクが低い。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>短所：&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>鍵共有（KEM）には使用できず、デジタル署名のみ。&lt;/li>
&lt;li>署名サイズが大きくなる傾向がある。&lt;/li>
&lt;li>「ステートフル」と「ステートレス」があり、ステートフル（XMSSなど）は鍵の使用回数を厳密に管理する必要があるため実装上の難易度が高い。&lt;/li>
&lt;/ul>
&lt;p>NISTは、ステートレスなハッシュベース署名として「SLH-DSA (旧 SPHINCS+)」を標準化しています。&lt;/p>
&lt;h3 id="3-多変数多項式ベース暗号multivariate-cryptography">3. 多変数多項式ベース暗号（Multivariate Cryptography）
&lt;/h3>&lt;p>多変数多項式暗号は、多数の変数を持つ連立二次多項式のシステムを解くことの難しさ（MQ問題：Multivariate Quadratic problem）を安全性の根拠とする方式です。この問題はNP困難であることが知られています。&lt;/p>
&lt;p>&lt;strong>仕組みの概要：&lt;/strong>
送信者は、公開鍵として渡された多数の変数を持つ複雑な方程式に、平文（またはハッシュ値）を代入して暗号文（署名）を作成します。正当な受信者は、秘密鍵として「方程式の構造を簡単に解ける形に変換する隠された情報（トラップドア）」を持っており、これを用いて復号（または署名検証）を行います。&lt;/p>
&lt;p>&lt;strong>長所：&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>署名サイズが非常に小さい。&lt;/li>
&lt;li>署名の検証速度が極めて高速。リソースが限られたIoTデバイスなどに適している。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>短所：&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>公開鍵のサイズが非常に大きい（数十キロバイト〜数百キロバイトになることもある）。&lt;/li>
&lt;li>過去に有力なアルゴリズム（Rainbowなど）が古典的な攻撃によって破られた事例があり、安全性に対する信頼を確立するのが他の方式に比べて難しい面がある。&lt;/li>
&lt;/ul>
&lt;h3 id="4-符号ベース暗号code-based-cryptography">4. 符号ベース暗号（Code-based Cryptography）
&lt;/h3>&lt;p>符号ベース暗号は、通信経路上でのエラーを訂正するために使われる「誤り訂正符号」の理論を暗号に応用したものです。1978年に提案された「McEliece（マックエリス）暗号」が最も有名であり、PQCの中でも最も歴史が古いものの一つです。&lt;/p>
&lt;p>&lt;strong>仕組みの概要：&lt;/strong>
送信者は、受信者の公開鍵（特定の構造を隠蔽した誤り訂正符号の生成行列）を用いて平文をエンコードし、さらに意図的なエラー（ノイズ）を付加して送信します。受信者は、秘密鍵を使ってエラーを除去し、平文を取り出します。暗号解読者は、構造を知らないただのランダムな符号からエラーを訂正しなければならず、これは「一般的なシンドローム復号問題」と呼ばれ、NP困難であることが証明されています。&lt;/p>
&lt;p>&lt;strong>長所：&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>40年以上の長きにわたり徹底的に研究され、これまで有効な攻撃が見つかっていないため、安全性の信頼性が極めて高い。&lt;/li>
&lt;li>暗号化・復号の処理が高速。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>短所：&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>公開鍵のサイズが非常に巨大（数メガバイトになることもある）。そのため、通信帯域やメモリに制限のある環境（TLSのハンドシェイクなど）での利用が難しい。&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="nistによるpqc標準化の最新動向">NISTによるPQC標準化の最新動向
&lt;/h2>&lt;p>米国国立標準技術研究所（NIST）は、2016年から世界中に向けて次世代の耐量子計算機暗号アルゴリズムの公募を開始し、数年間にわたる厳しい評価とラウンドを重ねてきました。&lt;/p>
&lt;p>2024年、NISTはついに正式な連邦情報処理標準（FIPS）として以下の3つのアルゴリズムを発表しました。これにより、世界中の組織が本番環境で実装を開始するための強固な土台が完成したことになります。&lt;/p>
&lt;h3 id="制定されたfips標準2024年">制定されたFIPS標準（2024年）
&lt;/h3>&lt;ol>
&lt;li>
&lt;p>&lt;strong>FIPS 203: ML-KEM（旧名: CRYSTALS-Kyber）&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>用途:&lt;/strong> 鍵カプセル化メカニズム（KEM）／暗号化・鍵共有&lt;/li>
&lt;li>&lt;strong>ベース技術:&lt;/strong> 格子暗号（Module-LWE）&lt;/li>
&lt;li>&lt;strong>特徴:&lt;/strong> 鍵サイズや速度のバランスが非常に良く、Web通信（TLS）やセキュアなメッセージングアプリなど、一般的なインターネット用途におけるデフォルトのPQC鍵共有として機能します。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>FIPS 204: ML-DSA（旧名: CRYSTALS-Dilithium）&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>用途:&lt;/strong> デジタル署名&lt;/li>
&lt;li>&lt;strong>ベース技術:&lt;/strong> 格子暗号（Module-LWE）&lt;/li>
&lt;li>&lt;strong>特徴:&lt;/strong> デジタル署名の主要な標準。効率的な処理が可能であり、ソフトウェアの署名やドキュメントの認証など、あらゆる電子署名用途の新しい標準となります。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>FIPS 205: SLH-DSA（旧名: SPHINCS+）&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>用途:&lt;/strong> デジタル署名&lt;/li>
&lt;li>&lt;strong>ベース技術:&lt;/strong> ハッシュベース暗号（ステートレス）&lt;/li>
&lt;li>&lt;strong>特徴:&lt;/strong> 万が一、将来的に格子暗号に脆弱性が発見された場合のバックアップとして機能するため、極めて重要な役割を担います。署名サイズは大きくなりますが、長期的な信頼性が求められる用途に適しています。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;h3 id="さらなる多様性の追求">さらなる多様性の追求
&lt;/h3>&lt;p>NISTは、最初の標準化プロセスを完了した一方で、さらなるアルゴリズムの探索を続けています。特に「格子暗号」に標準が偏っているため、 &lt;strong>アルゴリズムの多様性（Crypto Diversity）&lt;/strong> を確保することが重要視されています。鍵共有のバックアップ標準として、符号ベース暗号などの評価が進められており、PQCの基盤は今後さらに強固なものになっていく予定です。&lt;/p>
&lt;hr>
&lt;h2 id="pqcへの移行シナリオと課題クリプトアジリティの重要性">PQCへの移行シナリオと課題：「クリプト・アジリティ」の重要性
&lt;/h2>&lt;p>NISTから正式な標準規格がリリースされたことで、世界中の政府機関、金融機関、テクノロジー企業は、既存のRSA/ECCからPQCへの移行（マイグレーション）を本格化させます。NSA（米国国家安全保障局）などのガイドラインでも、早期の移行完了が推奨されています。&lt;/p>
&lt;h3 id="ハイブリッドアプローチの採用">ハイブリッドアプローチの採用
&lt;/h3>&lt;p>PQCアルゴリズムは新しいため、古典的な暗号と比べると「時間の試練」を経ていません。実装に潜むバグや新しい攻撃手法が発見されるリスクを考慮し、過渡期においては &lt;strong>「ハイブリッド方式」&lt;/strong> が推奨されています。これは、実績のある既存の暗号（例：ECDHE）と新しいPQC（例：ML-KEM）を組み合わせて鍵交換を行う方法です。現在、主要なブラウザやクラウドサービスではこの方式の試験導入が急速に進んでいます。&lt;/p>
&lt;h3 id="クリプトアジリティ暗号の俊敏性の実現">クリプト・アジリティ（暗号の俊敏性）の実現
&lt;/h3>&lt;p>企業やシステム開発者が今後最も意識すべきなのは、 &lt;strong>「クリプト・アジリティ（Crypto-Agility）」&lt;/strong> の確保です。将来アルゴリズムに欠陥が見つかったり新しい標準が登場したりした際に、システムを止めることなく迅速に暗号アルゴリズムを交換・更新できる柔軟なアーキテクチャ設計が不可欠です。&lt;/p>
&lt;p>自社のシステム内の「どこで」「どの暗号が」「何の目的で」使われているかを正確に把握する暗号インベントリ（CBOM：Cryptography Bill of Materials）の作成が、PQC移行に向けた重要な第一歩となります。&lt;/p>
&lt;hr>
&lt;h2 id="まとめ来るべきq-dayに備えて">まとめ：来るべき「Q-Day」に備えて
&lt;/h2>&lt;p>量子コンピュータの進化は、人類に多大な恩恵をもたらす一方で、現在のデジタル社会の根幹である暗号セキュリティに対する最大の脅威でもあります。耐量子計算機暗号（PQC）は、もはや「遠い未来の研究テーマ」ではありません。NISTによるFIPS標準の発行というマイルストーンを経て、PQCは本格的な「実装と移行」のフェーズへと突入しました。&lt;/p>
&lt;p>「Harvest Now, Decrypt Later」の脅威を考慮すれば、機密性の高いデータを扱うすべての組織にとって、PQCへの移行は「今すぐ」取り掛かるべき最優先課題です。次世代暗号の技術を深く理解し、システムのクリプト・アジリティを高めることで、来るべき量子コンピュータ時代を安全に乗り越えていきましょう。&lt;/p></description></item><item><title>量子コンピュータは本当にRSA暗号を破壊するのか？〜ショアのアルゴリズムと現在の到達点〜</title><link>http://kenji.blog/p/shors-algorithm-and-rsa-breaking/</link><pubDate>Sat, 05 Sep 2026 22:09:21 +0900</pubDate><guid>http://kenji.blog/p/shors-algorithm-and-rsa-breaking/</guid><description>&lt;img src="http://kenji.blog/p/shors-algorithm-and-rsa-breaking/quantum_breaking_rsa_1788613722990.jpg" alt="Featured image of post 量子コンピュータは本当にRSA暗号を破壊するのか？〜ショアのアルゴリズムと現在の到達点〜" />&lt;h2 id="はじめに暗号技術と量子コンピュータの交差点">はじめに：暗号技術と量子コンピュータの交差点
&lt;/h2>&lt;p>現代のインターネット社会において、通信の秘密を守るための基盤となっているのが「公開鍵暗号」です。その中でも代表的なものが、1977年にRon Rivest、Adi Shamir、Leonard Adlemanの3氏によって開発された「RSA暗号」です。私たちが毎日利用しているオンラインショッピングの決済、ウェブサイトの閲覧（HTTPS）、メールの送受信に至るまで、RSA暗号はインターネットインフラの心臓部として機能しています。&lt;/p>
&lt;p>しかし、「量子コンピュータ」の登場によって、この安全性が根底から覆される可能性が指摘されています。メディアでは「量子コンピュータが完成すれば、世界中のパスワードや暗号が数秒で解読されてしまう」といったセンセーショナルな見出しが躍ることもあります。果たして、それは本当なのでしょうか？&lt;/p>
&lt;p>本記事では、古典的な暗号解読手法であるGNFS（一般数体ふるい法）と、量子コンピュータを用いた暗号解読アルゴリズムの決定版である「ショアのアルゴリズム（Shor&amp;rsquo;s Algorithm）」の仕組みを深く掘り下げます。量子フーリエ変換や周期発見といった高度な概念を分かりやすく解説し、現在のNISQ（Noisy Intermediate-Scale Quantum）時代における量子ハードウェアの現状と、実際にRSA-2048を破るために必要なハードルについて詳細に検証していきます。&lt;/p>
&lt;hr>
&lt;h2 id="rsa暗号の根幹素因数分解の困難性">RSA暗号の根幹：素因数分解の困難性
&lt;/h2>&lt;p>RSA暗号の安全性は、数学における極めてシンプルな非対称性に依存しています。それは、「2つの巨大な素数を掛け合わせることは簡単だが、その掛け合わせた結果（合成数）から元の2つの素数を見つけ出す（素因数分解する）ことは極めて難しい」という事実です。&lt;/p>
&lt;p>例えば、 $ p = 61 $、 $ q = 53 $ という2つの素数があったとします。この掛け算 $ N = p \times q = 3233 $ を計算するのは一瞬です。しかし、「3233」という数字だけを与えられて、「これはどの素数とどの素数の掛け算か？」を解くのは、数字が大きくなればなるほど計算量が爆発的に増加します。&lt;/p>
&lt;p>現在主流となっているRSA-2048では、鍵長が2048ビット、つまり10進数にして約617桁にも及ぶ巨大な合成数 $ N $ が使われています。この $ N $ を素因数分解できれば、暗号は解読されたも同然となります。&lt;/p>
&lt;h3 id="古典コンピュータによる挑戦gnfs一般数体ふるい法">古典コンピュータによる挑戦：GNFS（一般数体ふるい法）
&lt;/h3>&lt;p>素因数分解問題を解くために、数学者や暗号学者は長年にわたり様々なアルゴリズムを開発してきました。その中で、古典コンピュータにおいて現在最も高速とされているのが &lt;strong>一般数体ふるい法（GNFS: General Number Field Sieve）&lt;/strong> です。&lt;/p>
&lt;p>GNFSは、巨大な数 $ N $ を素因数分解するために、整数環における計算をより抽象的な代数体（Number Field）に拡張して解析する手法です。大まかな流れとしては以下のようになります。&lt;/p>
&lt;ol>
&lt;li>&lt;strong>多項式の選択&lt;/strong> : $ N $ を根として持つような、適切な次数と係数を持つ多項式 $ f(x) $ を見つけます。&lt;/li>
&lt;li>&lt;strong>データ収集（ふるい分け）&lt;/strong> : 有理数体および代数体の上で、小さな素数（滑らかな数、Smooth numbers）に分解できるような数のペアを大量に探索します。このプロセスが「ふるい分け」と呼ばれ、最も時間を要する部分です。&lt;/li>
&lt;li>&lt;strong>行列の生成と簡約&lt;/strong> : 収集した関係式を元に巨大な疎行列（成分のほとんどが0の行列）を生成し、線形代数的な手法（ブロック・ランチョス法など）を用いて解を求めます。&lt;/li>
&lt;li>&lt;strong>平方根の計算&lt;/strong> : 最後に代数体上での平方根を計算し、$ N $ の因数（素因数）を導き出します。&lt;/li>
&lt;/ol>
&lt;p>GNFSの計算量は、非漸近的に $ O(\exp((\sqrt[3]{\frac{64}{9}} + o(1)) (\log N)^{\frac{1}{3}} (\log \log N)^{\frac{2}{3}})) $ と評価されます。これは「準指数関数的（Sub-exponential）」な時間計算量と呼ばれます。指数関数時間よりは速いものの、多項式時間（Polynomial time）よりは遥かに遅い計算量です。&lt;/p>
&lt;p>実際に、2020年には国際的な研究チームがGNFSを用いてRSA-250（829ビット、250桁の合成数）の素因数分解に成功しました。この計算には、世界中の計算機リソースをかき集めて約2700 CPUコア年という膨大な計算時間を費やしています。しかし、これが2048ビットとなると、必要な計算量は宇宙の寿命の数兆倍にも膨れ上がると言及されており、現在のスーパーコンピュータをどれだけ並列稼働させても、古典的な手法では現実的な時間内で解読することは不可能です。&lt;/p>
&lt;hr>
&lt;h2 id="量子コンピュータの切り札ショアのアルゴリズム">量子コンピュータの切り札：ショアのアルゴリズム
&lt;/h2>&lt;p>ここで登場するのが、1994年にピーター・ショア（Peter Shor）によって発表された「ショアのアルゴリズム」です。このアルゴリズムは、素因数分解問題を量子コンピュータ上で &lt;strong>多項式時間&lt;/strong> （ $ O((\log N)^3) $ ）で解くことができるという画期的なものでした。準指数関数時間と多項式時間の差は決定的なものであり、理論上、量子コンピュータを使えばRSA暗号は完全に破壊されることを意味します。&lt;/p>
&lt;h3 id="ショアのアルゴリズムの全体フロー">ショアのアルゴリズムの全体フロー
&lt;/h3>&lt;p>&lt;code>mermaid graph TD A[素因数分解したい数 N を入力] --&amp;gt; B[ランダムな整数 a を選択] B --&amp;gt; C{a と N の&amp;lt;br&amp;gt;最大公約数} C --&amp;gt;|1より大きい| D[幸運にも素因数を発見！] C --&amp;gt;|1 互いに素| E[量子コンピュータの出番] E --&amp;gt; F[関数 f_x = a^x mod N の&amp;lt;br&amp;gt;周期 r を量子フーリエ変換で求める] F --&amp;gt; G{周期 r が偶数 かつ&amp;lt;br&amp;gt;a^r/2 ≢ -1 mod N} G --&amp;gt;|Yes| H[最大公約数 gcd_a^r/2 ± 1, N を計算] H --&amp;gt; I((素因数分解 成功！)) G --&amp;gt;|No| B &lt;/code>&lt;/p>
&lt;p>ショアのアルゴリズムは、素因数分解という問題を直接解くのではなく、数論の定理を用いて「周期発見問題（Period Finding Problem）」という別の問題に変換し、それを量子コンピュータの特性を活かして高速に解くというアプローチをとります。&lt;/p>
&lt;h3 id="ステップ1素因数分解から周期発見問題への還元古典的処理">ステップ1：素因数分解から周期発見問題への還元（古典的処理）
&lt;/h3>&lt;p>アルゴリズムの最初のステップは古典コンピュータで行われます。
素因数分解したい数 $ N $ に対して、$ N $ と互いに素な（最大公約数が1の）ランダムな整数 $ a $ （ $ 1 &lt; a &lt; N $ ）を選びます。もし偶然にも最大公約数が1でなければ、その時点で見つかった公約数が $ N $ の素因数なので解読完了ですが、確率は極めて低いです。&lt;/p>
&lt;p>次に、以下のモジュロ方程式の列を考えます。
$ f(x) = a^x \pmod N $&lt;/p>
&lt;p>この関数 $ f(x) $ に $ x = 1, 2, 3, \dots $ と代入していくと、値はランダムなように見えますが、有限の範囲内で計算しているため、必ずどこかで元の値に戻り、同じ数列を繰り返します。この繰り返しの周期を $ r $ と呼びます。つまり、
$ a^r \equiv 1 \pmod N $
となる最小の正の整数 $ r $ を見つける問題、これが「周期発見問題」です。&lt;/p>
&lt;p>もしこの周期 $ r $ が見つかり、かつ $ r $ が偶数であれば、$ a^r - 1 \equiv 0 \pmod N $ となり、因数分解の公式を用いて
$ (a^{r/2} - 1)(a^{r/2} + 1) \equiv 0 \pmod N $
と変形できます。ここから、ユークリッドの互除法を使って $ N $ と $ a^{r/2} \pm 1 $ の最大公約数を計算することで、$ N $ の素因数が極めて高い確率で得られます。&lt;/p>
&lt;p>古典コンピュータで周期 $ r $ を見つけるためには、結局のところ指数関数的なステップが必要となり高速化できません。しかし、量子コンピュータならばこの周期 $ r $ を一瞬で（多項式時間で）見つけることができるのです。&lt;/p>
&lt;h3 id="ステップ2量子状態の準備と重ね合わせ">ステップ2：量子状態の準備と重ね合わせ
&lt;/h3>&lt;p>ここからが量子コンピュータの出番です。
量子コンピュータは、「0」と「1」の状態を同時に持つことができる「量子ビット（Qubit）」を使用します。ショアのアルゴリズムでは、入力を格納するレジスタ（第1レジスタ）と、計算結果を格納するレジスタ（第2レジスタ）の2つを用意します。&lt;/p>
&lt;p>まず、アダマールゲート（Hadamard gate）と呼ばれる量子ゲート操作を第1レジスタの全ての量子ビットに適用します。これにより、第1レジスタは考え得るすべての $ x $ の値（ $ 0 $ から $ 2^n-1 $ まで。$ n $ は十分大きなビット数）の &lt;strong>均等な重ね合わせ状態&lt;/strong> になります。&lt;/p>
&lt;p>つまり、量子コンピュータの内部には、$ x=0, 1, 2, 3, \dots $ という無数の入力値が同時に並行して存在している状態が作られます。&lt;/p>
&lt;h3 id="ステップ3量子モジュロべき乗算quantum-modular-exponentiation">ステップ3：量子モジュロべき乗算（Quantum Modular Exponentiation）
&lt;/h3>&lt;p>次に、第1レジスタの重ね合わせ状態を入力として、$ f(x) = a^x \pmod N $ を計算し、その結果を第2レジスタに格納します。
この計算は量子回路上のユニタリ変換として実行されるため、重ね合わせが保たれたまま、すべての $ x $ に対する $ f(x) $ の計算が「同時並行的に（量子並列性）」行われます。&lt;/p>
&lt;p>この時点での量子システム全体の空間は、
$ |x, a^x \bmod N\rangle $
という状態の膨大な重ね合わせになっています。&lt;/p>
&lt;p>しかし、ここで単純に第2レジスタを測定（観測）してしまうと、ランダムな $ a^x \bmod N $ の値が一つだけ確率的に選ばれ、それに連動して第1レジスタの $ x $ も一つに確定してしまいます。これでは古典コンピュータで一回計算したのと同じことで、周期 $ r $ を見つけることはできません。&lt;/p>
&lt;p>量子力学のルールでは、重ね合わせ状態の中身を直接覗き見ることはできないのです。では、どうやって全体の「周期」というグローバルな情報を抽出するのでしょうか？&lt;/p>
&lt;h3 id="ステップ4量子フーリエ変換qft-quantum-fourier-transform">ステップ4：量子フーリエ変換（QFT: Quantum Fourier Transform）
&lt;/h3>&lt;p>この壁を突破するショアのアルゴリズムの真骨頂が、第1レジスタに対する &lt;strong>量子フーリエ変換（QFT）&lt;/strong> の適用です。&lt;/p>
&lt;p>測定を行う前に、関数 $ f(x) $ の波の性質を解析します。第2レジスタを観測したと仮定しましょう。ある値 $ y $ が得られたとします。すると、第1レジスタの状態は「 $ a^x \pmod N = y $ となるような全ての $ x $ の重ね合わせ」に収縮します。
この $ x $ の値は、$ x_0, x_0 + r, x_0 + 2r, x_0 + 3r, \dots $ のように、周期 $ r $ の間隔で離散的に並んだ状態（一種の櫛状の確率振幅分布）になります。&lt;/p>
&lt;p>この状態に対して量子フーリエ変換（QFT）を適用します。古典的な離散フーリエ変換が時間領域の信号を周波数領域に変換するように、QFTは量子状態の確率振幅に干渉を起こさせます。&lt;/p>
&lt;p>QFTをかけると、量子干渉効果によって、周期 $ r $ と共鳴しない（位相が揃わない）誤った答えの確率は互いに打ち消し合ってゼロに近づき（破壊的干渉）、周期 $ r $ の情報を持つ正しい答えの確率だけが増幅されます（建設的干渉）。&lt;/p>
&lt;h3 id="ステップ5測定と連分数展開古典的後処理">ステップ5：測定と連分数展開（古典的後処理）
&lt;/h3>&lt;p>QFT適用後に第1レジスタを測定すると、非常に高い確率で $ c \approx \frac{j \cdot 2^n}{r} $ という形に近い整数 $ c $ が得られます（ $ j $ は未知の整数、$ 2^n $ はレジスタのサイズ）。&lt;/p>
&lt;p>この測定結果 $ c $ を古典コンピュータに戻し、$ \frac{c}{2^n} \approx \frac{j}{r} $ という分数を作ります。そして、数学的手法である「連分数展開（Continued fraction expansion）」を用いて近似値を計算することで、分母である周期 $ r $ を見事にあぶり出すことができます。&lt;/p>
&lt;p>$ r $ が分かれば、あとはステップ1の公式を使って $ N $ の素因数を計算し、RSA暗号は完全に解読されます。&lt;/p>
&lt;hr>
&lt;h2 id="現状の量子コンピュータnisqの実力と課題">現状の量子コンピュータ（NISQ）の実力と課題
&lt;/h2>&lt;p>理論的には完璧なショアのアルゴリズムですが、「明日にもRSA暗号が破られるのか？」と問われれば、答えは明確に「ノー」です。その理由は、現在の量子コンピュータのハードウェア技術の限界にあります。&lt;/p>
&lt;h3 id="nisqnoisy-intermediate-scale-quantum時代">NISQ（Noisy Intermediate-Scale Quantum）時代
&lt;/h3>&lt;p>現在我々が存在しているのは、「NISQ」と呼ばれる時代です。NISQデバイスは、数十から数百の物理量子ビットを持ちますが、ノイズに対して極めて脆弱です。&lt;/p>
&lt;p>量子ビットは、熱や電磁波などの外部環境の影響を受けやすく、量子状態が壊れてしまう「デコヒーレンス（量子もつれ喪失）」や、ゲート操作時の「ゲートエラー」が頻繁に発生します。ショアのアルゴリズムのような非常に深い（演算ステップ数が膨大な）量子回路を実行しようとすると、計算の途中でエラーが蓄積し、最終的な出力は意味を持たない完全なノイズになってしまいます。&lt;/p>
&lt;h3 id="物理量子ビットと論理量子ビット">物理量子ビットと論理量子ビット
&lt;/h3>&lt;p>このエラー問題を解決するために不可欠なのが「量子誤り訂正（Quantum Error Correction）」です。
古典コンピュータでも誤り訂正コードは使われていますが、量子状態の複製を禁じる「量子複製不可能定理」があるため、量子誤り訂正は非常に複雑です。&lt;/p>
&lt;p>量子誤り訂正では、「表面符号（Surface Code）」などの技術を用いて、多数のノイズだらけの「物理量子ビット」を組み合わせることで、エラーのない理想的な1つの「論理量子ビット」を作り出します。&lt;/p>
&lt;p>現在のエラー率を前提とすると、1つの論理量子ビットを作るためには、およそ1,000〜10,000個の物理量子ビットが必要になると試算されています。これを「誤り訂正のオーバーヘッド」と呼びます。&lt;/p>
&lt;h3 id="rsa-2048を破壊するために必要なリソースとは">RSA-2048を破壊するために必要なリソースとは？
&lt;/h3>&lt;p>では、実際にRSA-2048を解読するために、ショアのアルゴリズムを走らせるにはどれくらいのリソースが必要なのでしょうか？&lt;/p>
&lt;p>Craig Gidney (Google) と Martin Ekerå による2021年の論文による画期的なリソース推定では、最適化されたショアのアルゴリズムを使用し、表面符号による誤り訂正を行った場合、以下のリソースが必要になるとされています。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>論理量子ビット数&lt;/strong> : 約 4,096 個&lt;/li>
&lt;li>&lt;strong>物理量子ビット数 ** : ** 約 2000万個&lt;/strong> （エラー率 $10^{-3}$ 程度を仮定）&lt;/li>
&lt;li>&lt;strong>計算時間&lt;/strong> : 約 8時間（物理ゲート操作が数百万〜数十億回必要）&lt;/li>
&lt;/ul>
&lt;p>これに対して、現在の量子ハードウェアの到達点はどうでしょうか。
2023年末にIBMが発表した超伝導量子プロセッサ「Condor（コンドル）」は 1,121 量子ビットです。また、論理量子ビットの生成に関する画期的な研究（ハーバード大学やQuEra社などによる中性原子量子コンピュータを用いた48個の論理量子ビットの生成など）も登場していますが、まだ「ノイズのない完璧な演算」を長時間連続して実行できる段階にはありません。&lt;/p>
&lt;p>数千の物理量子ビットから、 &lt;strong>2000万個&lt;/strong> の実用的な物理量子ビット（かつ相互結線され、極低温で安定動作し、超高速で制御信号を処理できるシステム）へのスケールアップは、工学的にとてつもない壁（配線問題、冷却能力の限界、制御エレクトロニクスの肥大化）が存在します。多くの専門家は、RSA-2048を解読可能な「フォールトトレラント（誤り耐性）量子コンピュータ（FTQC）」が実現するには、少なくとも10年から30年、あるいはそれ以上の年月が必要だと予測しています。&lt;/p>
&lt;hr>
&lt;h2 id="忍び寄るstore-now-decrypt-laterの脅威とpqcの夜明け">忍び寄る「Store Now, Decrypt Later」の脅威とPQCの夜明け
&lt;/h2>&lt;p>「まだ10年以上かかるなら安心だ」と考えるのは早計です。現在、国家の機密情報や医療データ、長期的なインフラ設計など、数十年先まで秘密を担保しなければならないデータが存在します。&lt;/p>
&lt;p>ここで懸念されているのが、 &lt;strong>「Store Now, Decrypt Later（今保存して、後で解読する）」&lt;/strong> という攻撃手法です。悪意のある国家や組織が、現在のRSAやECC（楕円曲線暗号）で暗号化された通信データをすべて傍受し、ストレージに保存しておくのです。そして10年後、20年後に強力な量子コンピュータが完成した瞬間に、ショアのアルゴリズムを用いて過去のデータをすべて解読し、秘密を暴露するという手法です。&lt;/p>
&lt;p>このタイムラグの脅威に対抗するため、NIST（米国国立標準技術研究所）を中心に、 &lt;strong>「耐量子計算機暗号（PQC: Post-Quantum Cryptography）」&lt;/strong> の標準化プロセスが急ピッチで進められてきました。&lt;/p>
&lt;p>PQCは、量子コンピュータを用いても解読が困難（つまり、ショアのアルゴリズムが適用できない）な数学的問題をベースにした新しい暗号アルゴリズムです。主なアプローチとして以下のようなものがあります。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>格子暗号（Lattice-based cryptography）&lt;/strong> : LWE（Learning with Errors）問題などを基礎とする。NISTの標準化で主流（Kyber、Dilithiumなど）。&lt;/li>
&lt;li>&lt;strong>符号ベース暗号（Code-based cryptography）&lt;/strong> : 誤り訂正符号の復号問題の困難性に依存。&lt;/li>
&lt;li>&lt;strong>多変数多項式暗号（Multivariate cryptography）&lt;/strong> : 多変数の連立二次方程式を解く困難性に依存。&lt;/li>
&lt;li>&lt;strong>ハッシュベース署名（Hash-based signatures）&lt;/strong> : ハッシュ関数の安全性のみに依存するデジタル署名。&lt;/li>
&lt;/ul>
&lt;p>すでにGoogle ChromeやAppleのiMessageなど、主要なソフトウェアやプラットフォームではPQCの導入テストやハイブリッド実装が開始されています。&lt;/p>
&lt;h2 id="おわりに">おわりに
&lt;/h2>&lt;p>量子コンピュータは、SFの世界の夢物語から現実の工学的挑戦へと移行しています。ショアのアルゴリズムは、数学と量子力学が融合した人類の偉大な知的成果ですが、同時に我々のデジタル社会の基盤を揺るがす「破壊的な力」を秘めています。&lt;/p>
&lt;p>RSA暗号が明日すぐに使えなくなるわけではありません。しかし、量子技術の進化と「Store Now, Decrypt Later」のリスクを鑑みれば、PQCへの移行という暗号史に残る大規模なマイグレーションはすでに始まっています。我々は今、情報セキュリティにおけるパラダイムシフトの最前線を目撃しているのです。&lt;/p></description></item><item><title>【完全解剖】最強の暗号解読アルゴリズム「GNFS」をC++で実装して理解する</title><link>http://kenji.blog/p/gnfs-cpp-implementation/</link><pubDate>Sat, 05 Sep 2026 13:04:59 +0900</pubDate><guid>http://kenji.blog/p/gnfs-cpp-implementation/</guid><description>&lt;img src="http://kenji.blog/p/gnfs-cpp-implementation/gnfs_cpp_blog_eyecatch_1788580949217.jpg" alt="Featured image of post 【完全解剖】最強の暗号解読アルゴリズム「GNFS」をC++で実装して理解する" />&lt;h1 id="完全解剖最強の暗号解読アルゴリズムgnfsをcで実装して理解する">【完全解剖】最強の暗号解読アルゴリズム「GNFS」をC++で実装して理解する
&lt;/h1>&lt;p>現代のインターネットを根底から支えている「RSA暗号」。その堅牢性は「巨大な合成数を素因数分解することは、現在のコンピュータでは事実上不可能である」という数学的信念に依存しています。&lt;/p>
&lt;p>しかし、人類は決して諦めていません。現在、古典コンピュータ（量子コンピュータではない通常のコンピュータ）において、巨大な素因数分解を行うための **人類最強・最先端のアルゴリズム ** が存在します。それが &lt;strong>「一般数体篩法（GNFS：General Number Field Sieve）」&lt;/strong> です。&lt;/p>
&lt;p>本記事では、このGNFSの最先端の計算ロジックを、C++（Boostライブラリの多倍長整数 &lt;code>boost::multiprecision&lt;/code> を使用）で厳密にモデル化した実装コードを全公開し、その裏側にある「代数的整数論」の深淵を徹底的に解説します。&lt;/p>
&lt;p>数学の神秘と、それをねじ伏せるコンピュータサイエンスの力技を、ぜひソースコードとともに堪能してください。&lt;/p>
&lt;hr>
&lt;h2 id="1-gnfs-最先端ロジックフレームワーク全ソースコード">1. GNFS 最先端ロジック・フレームワーク（全ソースコード）
&lt;/h2>&lt;p>まずは、今回解説するGNFSのC++実装の全貌を掲載します。実際の数体篩法（CADO-NFSなど）は数十万行に及ぶ超巨大な分散システムですが、本コードはGNFSを構成する &lt;strong>「5つの必須パイプライン（フェーズ）」&lt;/strong> を抽出してクラス設計し、数学的な意味を失わずに最小構成でモデル化したものです。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt"> 10
&lt;/span>&lt;span class="lnt"> 11
&lt;/span>&lt;span class="lnt"> 12
&lt;/span>&lt;span class="lnt"> 13
&lt;/span>&lt;span class="lnt"> 14
&lt;/span>&lt;span class="lnt"> 15
&lt;/span>&lt;span class="lnt"> 16
&lt;/span>&lt;span class="lnt"> 17
&lt;/span>&lt;span class="lnt"> 18
&lt;/span>&lt;span class="lnt"> 19
&lt;/span>&lt;span class="lnt"> 20
&lt;/span>&lt;span class="lnt"> 21
&lt;/span>&lt;span class="lnt"> 22
&lt;/span>&lt;span class="lnt"> 23
&lt;/span>&lt;span class="lnt"> 24
&lt;/span>&lt;span class="lnt"> 25
&lt;/span>&lt;span class="lnt"> 26
&lt;/span>&lt;span class="lnt"> 27
&lt;/span>&lt;span class="lnt"> 28
&lt;/span>&lt;span class="lnt"> 29
&lt;/span>&lt;span class="lnt"> 30
&lt;/span>&lt;span class="lnt"> 31
&lt;/span>&lt;span class="lnt"> 32
&lt;/span>&lt;span class="lnt"> 33
&lt;/span>&lt;span class="lnt"> 34
&lt;/span>&lt;span class="lnt"> 35
&lt;/span>&lt;span class="lnt"> 36
&lt;/span>&lt;span class="lnt"> 37
&lt;/span>&lt;span class="lnt"> 38
&lt;/span>&lt;span class="lnt"> 39
&lt;/span>&lt;span class="lnt"> 40
&lt;/span>&lt;span class="lnt"> 41
&lt;/span>&lt;span class="lnt"> 42
&lt;/span>&lt;span class="lnt"> 43
&lt;/span>&lt;span class="lnt"> 44
&lt;/span>&lt;span class="lnt"> 45
&lt;/span>&lt;span class="lnt"> 46
&lt;/span>&lt;span class="lnt"> 47
&lt;/span>&lt;span class="lnt"> 48
&lt;/span>&lt;span class="lnt"> 49
&lt;/span>&lt;span class="lnt"> 50
&lt;/span>&lt;span class="lnt"> 51
&lt;/span>&lt;span class="lnt"> 52
&lt;/span>&lt;span class="lnt"> 53
&lt;/span>&lt;span class="lnt"> 54
&lt;/span>&lt;span class="lnt"> 55
&lt;/span>&lt;span class="lnt"> 56
&lt;/span>&lt;span class="lnt"> 57
&lt;/span>&lt;span class="lnt"> 58
&lt;/span>&lt;span class="lnt"> 59
&lt;/span>&lt;span class="lnt"> 60
&lt;/span>&lt;span class="lnt"> 61
&lt;/span>&lt;span class="lnt"> 62
&lt;/span>&lt;span class="lnt"> 63
&lt;/span>&lt;span class="lnt"> 64
&lt;/span>&lt;span class="lnt"> 65
&lt;/span>&lt;span class="lnt"> 66
&lt;/span>&lt;span class="lnt"> 67
&lt;/span>&lt;span class="lnt"> 68
&lt;/span>&lt;span class="lnt"> 69
&lt;/span>&lt;span class="lnt"> 70
&lt;/span>&lt;span class="lnt"> 71
&lt;/span>&lt;span class="lnt"> 72
&lt;/span>&lt;span class="lnt"> 73
&lt;/span>&lt;span class="lnt"> 74
&lt;/span>&lt;span class="lnt"> 75
&lt;/span>&lt;span class="lnt"> 76
&lt;/span>&lt;span class="lnt"> 77
&lt;/span>&lt;span class="lnt"> 78
&lt;/span>&lt;span class="lnt"> 79
&lt;/span>&lt;span class="lnt"> 80
&lt;/span>&lt;span class="lnt"> 81
&lt;/span>&lt;span class="lnt"> 82
&lt;/span>&lt;span class="lnt"> 83
&lt;/span>&lt;span class="lnt"> 84
&lt;/span>&lt;span class="lnt"> 85
&lt;/span>&lt;span class="lnt"> 86
&lt;/span>&lt;span class="lnt"> 87
&lt;/span>&lt;span class="lnt"> 88
&lt;/span>&lt;span class="lnt"> 89
&lt;/span>&lt;span class="lnt"> 90
&lt;/span>&lt;span class="lnt"> 91
&lt;/span>&lt;span class="lnt"> 92
&lt;/span>&lt;span class="lnt"> 93
&lt;/span>&lt;span class="lnt"> 94
&lt;/span>&lt;span class="lnt"> 95
&lt;/span>&lt;span class="lnt"> 96
&lt;/span>&lt;span class="lnt"> 97
&lt;/span>&lt;span class="lnt"> 98
&lt;/span>&lt;span class="lnt"> 99
&lt;/span>&lt;span class="lnt">100
&lt;/span>&lt;span class="lnt">101
&lt;/span>&lt;span class="lnt">102
&lt;/span>&lt;span class="lnt">103
&lt;/span>&lt;span class="lnt">104
&lt;/span>&lt;span class="lnt">105
&lt;/span>&lt;span class="lnt">106
&lt;/span>&lt;span class="lnt">107
&lt;/span>&lt;span class="lnt">108
&lt;/span>&lt;span class="lnt">109
&lt;/span>&lt;span class="lnt">110
&lt;/span>&lt;span class="lnt">111
&lt;/span>&lt;span class="lnt">112
&lt;/span>&lt;span class="lnt">113
&lt;/span>&lt;span class="lnt">114
&lt;/span>&lt;span class="lnt">115
&lt;/span>&lt;span class="lnt">116
&lt;/span>&lt;span class="lnt">117
&lt;/span>&lt;span class="lnt">118
&lt;/span>&lt;span class="lnt">119
&lt;/span>&lt;span class="lnt">120
&lt;/span>&lt;span class="lnt">121
&lt;/span>&lt;span class="lnt">122
&lt;/span>&lt;span class="lnt">123
&lt;/span>&lt;span class="lnt">124
&lt;/span>&lt;span class="lnt">125
&lt;/span>&lt;span class="lnt">126
&lt;/span>&lt;span class="lnt">127
&lt;/span>&lt;span class="lnt">128
&lt;/span>&lt;span class="lnt">129
&lt;/span>&lt;span class="lnt">130
&lt;/span>&lt;span class="lnt">131
&lt;/span>&lt;span class="lnt">132
&lt;/span>&lt;span class="lnt">133
&lt;/span>&lt;span class="lnt">134
&lt;/span>&lt;span class="lnt">135
&lt;/span>&lt;span class="lnt">136
&lt;/span>&lt;span class="lnt">137
&lt;/span>&lt;span class="lnt">138
&lt;/span>&lt;span class="lnt">139
&lt;/span>&lt;span class="lnt">140
&lt;/span>&lt;span class="lnt">141
&lt;/span>&lt;span class="lnt">142
&lt;/span>&lt;span class="lnt">143
&lt;/span>&lt;span class="lnt">144
&lt;/span>&lt;span class="lnt">145
&lt;/span>&lt;span class="lnt">146
&lt;/span>&lt;span class="lnt">147
&lt;/span>&lt;span class="lnt">148
&lt;/span>&lt;span class="lnt">149
&lt;/span>&lt;span class="lnt">150
&lt;/span>&lt;span class="lnt">151
&lt;/span>&lt;span class="lnt">152
&lt;/span>&lt;span class="lnt">153
&lt;/span>&lt;span class="lnt">154
&lt;/span>&lt;span class="lnt">155
&lt;/span>&lt;span class="lnt">156
&lt;/span>&lt;span class="lnt">157
&lt;/span>&lt;span class="lnt">158
&lt;/span>&lt;span class="lnt">159
&lt;/span>&lt;span class="lnt">160
&lt;/span>&lt;span class="lnt">161
&lt;/span>&lt;span class="lnt">162
&lt;/span>&lt;span class="lnt">163
&lt;/span>&lt;span class="lnt">164
&lt;/span>&lt;span class="lnt">165
&lt;/span>&lt;span class="lnt">166
&lt;/span>&lt;span class="lnt">167
&lt;/span>&lt;span class="lnt">168
&lt;/span>&lt;span class="lnt">169
&lt;/span>&lt;span class="lnt">170
&lt;/span>&lt;span class="lnt">171
&lt;/span>&lt;span class="lnt">172
&lt;/span>&lt;span class="lnt">173
&lt;/span>&lt;span class="lnt">174
&lt;/span>&lt;span class="lnt">175
&lt;/span>&lt;span class="lnt">176
&lt;/span>&lt;span class="lnt">177
&lt;/span>&lt;span class="lnt">178
&lt;/span>&lt;span class="lnt">179
&lt;/span>&lt;span class="lnt">180
&lt;/span>&lt;span class="lnt">181
&lt;/span>&lt;span class="lnt">182
&lt;/span>&lt;span class="lnt">183
&lt;/span>&lt;span class="lnt">184
&lt;/span>&lt;span class="lnt">185
&lt;/span>&lt;span class="lnt">186
&lt;/span>&lt;span class="lnt">187
&lt;/span>&lt;span class="lnt">188
&lt;/span>&lt;span class="lnt">189
&lt;/span>&lt;span class="lnt">190
&lt;/span>&lt;span class="lnt">191
&lt;/span>&lt;span class="lnt">192
&lt;/span>&lt;span class="lnt">193
&lt;/span>&lt;span class="lnt">194
&lt;/span>&lt;span class="lnt">195
&lt;/span>&lt;span class="lnt">196
&lt;/span>&lt;span class="lnt">197
&lt;/span>&lt;span class="lnt">198
&lt;/span>&lt;span class="lnt">199
&lt;/span>&lt;span class="lnt">200
&lt;/span>&lt;span class="lnt">201
&lt;/span>&lt;span class="lnt">202
&lt;/span>&lt;span class="lnt">203
&lt;/span>&lt;span class="lnt">204
&lt;/span>&lt;span class="lnt">205
&lt;/span>&lt;span class="lnt">206
&lt;/span>&lt;span class="lnt">207
&lt;/span>&lt;span class="lnt">208
&lt;/span>&lt;span class="lnt">209
&lt;/span>&lt;span class="lnt">210
&lt;/span>&lt;span class="lnt">211
&lt;/span>&lt;span class="lnt">212
&lt;/span>&lt;span class="lnt">213
&lt;/span>&lt;span class="lnt">214
&lt;/span>&lt;span class="lnt">215
&lt;/span>&lt;span class="lnt">216
&lt;/span>&lt;span class="lnt">217
&lt;/span>&lt;span class="lnt">218
&lt;/span>&lt;span class="lnt">219
&lt;/span>&lt;span class="lnt">220
&lt;/span>&lt;span class="lnt">221
&lt;/span>&lt;span class="lnt">222
&lt;/span>&lt;span class="lnt">223
&lt;/span>&lt;span class="lnt">224
&lt;/span>&lt;span class="lnt">225
&lt;/span>&lt;span class="lnt">226
&lt;/span>&lt;span class="lnt">227
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;vector&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;cmath&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;map&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;set&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;chrono&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;boost/multiprecision/cpp_int.hpp&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Boost.Multiprecisionの多倍長整数を使用
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">using&lt;/span> &lt;span class="k">namespace&lt;/span> &lt;span class="n">boost&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">multiprecision&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// [SOTA GNFS] General Number Field Sieve (一般数体篩法) 最先端ロジックフレームワーク
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">//
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// 本コードは、CADO-NFS等で用いられる最先端のGNFSの5つのパイプラインを
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// C++ (Boost) のクラス設計として厳密にモデル化したものです。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">struct&lt;/span> &lt;span class="nc">Relation&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">int64_t&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">int64_t&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">uint32_t&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">rational_primes&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">uint32_t&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">algebraic_primes&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Phase 1: Polynomial Selection (KleinJungのアルゴリズム)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">class&lt;/span> &lt;span class="nc">PolynomialSelector&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">int&lt;/span> &lt;span class="n">degree&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">cpp_int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// 代数側多項式 f(x)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">cpp_int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">g&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// 有理側多項式 g(x) = x - m
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">PolynomialSelector&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">d&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">degree&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">d&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// base-m 展開を基にした初期多項式の生成 (実際はより高度な格子基底簡約 LLL を使用)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">cpp_int&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[Phase 1] Polynomial Selection (Degree &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">degree&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;) starting...&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 簡易的な base-m 展開 (d次)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// m = N^(1/d)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">N_copy&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">m&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 簡易なmの概算 (Boostの関数を利用しない近似)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">low&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">high&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">low&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">high&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">mid&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">low&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">high&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">low&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">degree&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="o">++&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">*=&lt;/span> &lt;span class="n">mid&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mid&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">low&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mid&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="n">high&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mid&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">f&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">resize&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">degree&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">temp&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">degree&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="o">++&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">f&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">temp&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">temp&lt;/span> &lt;span class="o">/=&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">g&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">m&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">};&lt;/span> &lt;span class="c1">// g(x) = x - m
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; -&amp;gt; m = &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; -&amp;gt; f(x) = &amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">degree&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="o">--&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;x^&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">i&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="o">?&lt;/span> &lt;span class="s">&amp;#34; + &amp;#34;&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">[Phase 1] Complete.&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Phase 2: Lattice Sieving (格子篩法)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// 近年のGNFSは、Line Sieve（直線篩）ではなく、Franke-Kleinjungらによる
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// 特殊q格子篩 (Special-q Lattice Sieving) を用いるのがデファクトスタンダードです。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">class&lt;/span> &lt;span class="nc">LatticeSieve&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">uint32_t&lt;/span> &lt;span class="n">rational_bound&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">uint32_t&lt;/span> &lt;span class="n">algebraic_bound&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">uint32_t&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">rational_fb&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">uint32_t&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">algebraic_fb&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">LatticeSieve&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">uint32_t&lt;/span> &lt;span class="n">rb&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">uint32_t&lt;/span> &lt;span class="n">ab&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">rational_bound&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">rb&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">algebraic_bound&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ab&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">void&lt;/span> &lt;span class="nf">generate_factor_bases&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[Phase 2] Generating Factor Bases (Rational Bound: &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">rational_bound&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;, Algebraic Bound: &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">algebraic_bound&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;)&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// (省略) 実際には素数生成とルジャンドル記号等での絞り込みを行う
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Relation&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">sieve&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">PolynomialSelector&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">poly&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[Phase 2] Special-q Lattice Sieving active...&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Relation&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">relations&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// モック実装: 実際の格子篩は数百GBのメモリ空間をブロック単位でスキャンする
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// (a, b) のペアを特殊素数 q ごとの格子 (a = i*q + j*...) にマッピングし、
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// キャッシュ効率を極限まで高めたシーブ(篩)を実行する。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// デモ用にダミーのリレーションを1つ追加
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">Relation&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">17&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">r&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">rational_primes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">r&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">algebraic_primes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">7&lt;/span>&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">relations&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">push_back&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[Phase 2] Found &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">relations&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">size&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; relations.&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">relations&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Phase 3: Filtering (特異点パージとクリークマージ)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">class&lt;/span> &lt;span class="nc">Filter&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">void&lt;/span> &lt;span class="n">reduce_matrix&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Relation&lt;/span>&lt;span class="o">&amp;gt;&amp;amp;&lt;/span> &lt;span class="n">relations&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[Phase 3] Filtering Relations...&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 1. Singleton removal (1度しか出現しない素数を持つリレーションの削除)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// 2. Clique merging (疎な行列を密にするためのリレーション結合)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// 実際にはUnion-Findアルゴリズムなどで数億行の行列を数百万行まで圧縮する。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[Phase 3] Matrix size reduced optimally.&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Phase 4: Linear Algebra over GF(2) (Block Wiedemann 法)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">class&lt;/span> &lt;span class="nc">LinearAlgebraGF2&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 近年のスパコン環境では Block Lanczos 法よりも、分散コンピューティングに
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// 適した Block Wiedemann 法 (Coppersmith実装) が最先端として利用される。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&amp;gt;&lt;/span> &lt;span class="n">solve_nullspace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Relation&lt;/span>&lt;span class="o">&amp;gt;&amp;amp;&lt;/span> &lt;span class="n">relations&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[Phase 4] Block Wiedemann algorithm over GF(2) starting...&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// スパース行列(疎行列)とベクトルの積演算を反復し、
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// M * x = 0 mod 2 となる解ベクトル(カーネル)を複数見つける。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&amp;gt;&lt;/span> &lt;span class="n">dependencies&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// 依存関係のリスト
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// ダミーデータ
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">dependencies&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">push_back&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[Phase 4] Found &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">dependencies&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">size&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; linear dependencies (perfect squares).&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">dependencies&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Phase 5: Algebraic Square Root (代数的平方根)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">class&lt;/span> &lt;span class="nc">AlgebraicSquareRoot&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">void&lt;/span> &lt;span class="n">compute_and_factor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Relation&lt;/span>&lt;span class="o">&amp;gt;&amp;amp;&lt;/span> &lt;span class="n">relations&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&amp;amp;&lt;/span> &lt;span class="n">dep&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="n">cpp_int&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[Phase 5] Algebraic Square Root computation...&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 1. 有理側の平方根 V の計算 (単純な整数演算)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">V&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// V = sqrt( prod(a - bm) ) mod N
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 2. 代数側の平方根 gamma の計算 (Montgomery&amp;#39;s method 等)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// 巨大な代数体 O_K の要素 gamma を求め、準同型写像 phi で現実の世界にマッピングする
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// Y = phi(gamma) mod N
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">Y&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// イデアル類群と単数群の障害(Obstruction)を回避するため、
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// Phase 2と4で平方剰余指標(Quadratic Characters)の列が追加されている前提。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; -&amp;gt; Homomorphism map phi applied.&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[Phase 5] Calculating GCD(V - Y, N)...&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">factor&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">V&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">Y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// GCD(X-Y, N)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">factor&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">factor&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">================================================================&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[SUCCESS] Non-trivial factor found: &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">factor&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; Other factor: &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">N&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="n">factor&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;================================================================&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[FAILURE] Trivial solution. Trying next dependency...&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Main Execution Pipeline
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;================================================================&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; [SOTA GNFS] General Number Field Sieve Engine (Boost C++) &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;================================================================&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// RSA-270等、素因数分解したい巨大な合成数 N
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;233108530344407544527637656910680524145619812480305449042948611968495918245135782867888369318577116418213919268572658314913060672626911354027609793166341626693946596196427744273886601876896313468704059066746903123910748277606548649151920812699309766587514735456594993207&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 多項式の次数 (130桁超えの場合は通常 5次〜6次 を選択)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">degree&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">6&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// パイプラインの初期化
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">PolynomialSelector&lt;/span> &lt;span class="n">poly_select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">degree&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">LatticeSieve&lt;/span> &lt;span class="n">sieve&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">10000000&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">20000000&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// 実際のバウンドは数千万〜数億
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">Filter&lt;/span> &lt;span class="n">filter&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">LinearAlgebraGF2&lt;/span> &lt;span class="n">linalg&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">AlgebraicSquareRoot&lt;/span> &lt;span class="n">sqrt_step&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">auto&lt;/span> &lt;span class="n">start_time&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">chrono&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">high_resolution_clock&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">now&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 1. 多項式選択
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">poly_select&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">N&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 2. 篩（シーブ）処理
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">sieve&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">generate_factor_bases&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Relation&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">relations&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sieve&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">sieve&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">poly_select&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 3. フィルタリング（行列圧縮）
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">filter&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">reduce_matrix&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">relations&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 4. 線形代数（GF(2)上のヌルスペース探索）
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&amp;gt;&lt;/span> &lt;span class="n">dependencies&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">linalg&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">solve_nullspace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">relations&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 5. 代数的平方根の計算とGCD
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="k">auto&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="nl">dep&lt;/span> &lt;span class="p">:&lt;/span> &lt;span class="n">dependencies&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sqrt_step&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">compute_and_factor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">relations&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">dep&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">auto&lt;/span> &lt;span class="n">end_time&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">chrono&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">high_resolution_clock&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">now&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">chrono&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">duration&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">double&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">elapsed&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">end_time&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">start_time&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">[System] SOTA GNFS Pipeline completed in &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">elapsed&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">count&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; seconds.&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>それでは、このコードがどのようにして暗号の壁を破壊していくのか。5つのフェーズごとに、その緻密なアルゴリズムと高度な数学をかみ砕いて解説していきます。&lt;/p>
&lt;hr>
&lt;h2 id="2-gnfsの最終目的-x2-equiv-y2-pmod-n">2. GNFSの最終目的： $X^2 \equiv Y^2 \pmod N$
&lt;/h2>&lt;p>GNFSのみならず、現代の巨大素因数分解アルゴリズムのほとんどが目指すゴールは、次の合同式を満たす非自明なペア $(X, Y)$ を見つけることです。&lt;/p>
$$X^2 \equiv Y^2 \pmod N$$
&lt;p>この式は、「$X^2$ と $Y^2$ を $N$ で割った余りが等しい」ことを意味します。これを変形すると、
$X^2 - Y^2 \equiv 0 \pmod N$
つまり、$(X-Y)(X+Y)$ が $N$ の倍数になります。&lt;/p>
&lt;p>もし $X \not\equiv \pm Y \pmod N$ （非自明な解）であれば、$(X-Y)$ と $N$ の間には「1より大きく $N$ より小さい公約数」が存在することになります。
ここで、ユークリッドの互除法を用いて &lt;strong>$\gcd(X-Y, N)$&lt;/strong> を計算すれば、$N$ の素因数がいとも簡単に求まります。&lt;/p>
&lt;p>しかし、この $X$ と $Y$ を見つけるのは砂漠から針を探すようなもの。そこでGNFSは、「現実の整数の世界」と「多項式の代数体の世界」という &lt;strong>2つの世界&lt;/strong> を作り出し、計算を分散させるという天才的なアプローチをとります。&lt;/p>
&lt;hr>
&lt;h2 id="3-phase-1-多項式選択polynomial-selection">3. Phase 1: 多項式選択（Polynomial Selection）
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">PolynomialSelector&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">cpp_int&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// m = N^(1/d) の計算と base-m 展開
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">degree&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="o">++&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">f&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">temp&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">temp&lt;/span> &lt;span class="o">/=&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">g&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">m&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">};&lt;/span> &lt;span class="c1">// g(x) = x - m
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>GNFSの最初のステップは、2つの世界を橋渡しするための「魔法の多項式」を作ることです。
巨大な数 $N$ に対して、整数 $m$ を選びます。通常 $m \approx N^{1/d}$ となるように選びます（コード中では $d=6$ 次の多項式を想定）。&lt;/p>
&lt;p>そして、$N$ を $m$ 進数展開し、その係数を使って多項式 $f(x)$ を構築します。
&lt;/p>
$$N = c_d m^d + c_{d-1} m^{d-1} + \dots + c_1 m + c_0$$
$$f(x) = c_d x^d + c_{d-1} x^{d-1} + \dots + c_1 x + c_0$$
&lt;p>この多項式 $f(x)$ には、 &lt;strong>「変数 $x$ に $m$ を代入すると、ちょうど $N$ になる（$f(m) = N$）」&lt;/strong> という極めて重要な性質があります。言い換えれば、$f(m) \equiv 0 \pmod N$ です。
有理側の多項式は $g(x) = x - m$ と定義されます。&lt;/p>
&lt;p>これにより、$f(x)=0$ の根 $\alpha$ が支配する &lt;strong>「代数体の世界 $\mathbb{Z}[\alpha]$」&lt;/strong> と、通常の &lt;strong>「有理数（整数）の世界 $\mathbb{Z}$」&lt;/strong> が、$x \to m$ という「環準同型写像（Homomorphism）」によって強固に結びつけられます。&lt;/p>
&lt;p>最先端のCADO-NFS等では、KleinJungのアルゴリズムやLLL格子基底簡約アルゴリズムを用いて、多項式の係数が極端に大きくならず、かつ後続のステップで素数が出現しやすい（滑らかになりやすい）ような「最高に都合の良い多項式 $f(x)$」を数ヶ月かけて探索します。&lt;/p>
&lt;hr>
&lt;h2 id="4-phase-2-特殊-q-格子篩法special-q-lattice-sieving">4. Phase 2: 特殊 $q$ 格子篩法（Special-q Lattice Sieving）
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">LatticeSieve&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Relation&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">sieve&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">PolynomialSelector&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">poly&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// (a, b) のペアを特殊素数 q ごとの格子にマッピングし、
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// キャッシュ効率を極限まで高めたシーブ(篩)を実行する。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>2つの世界を用意したら、次はその両方の世界で「滑らかな数（小さな素数だけで構成される数）」を探すステップに入ります。
整数ペア $(a, b)$ を無数に生成し、以下の2つの値を計算します。&lt;/p>
&lt;ol>
&lt;li>&lt;strong>有理側の値&lt;/strong> ： $a - bm$&lt;/li>
&lt;li>&lt;strong>代数側のノルム&lt;/strong> ： $b^d f(a/b)$&lt;/li>
&lt;/ol>
&lt;p>GNFSの目的は、この &lt;strong>「有理側と代数側の値が、両方とも小さな素因数のみで完全に分解できるペア（Relation：リレーション）」&lt;/strong> を数千万〜数億個集めることです。&lt;/p>
&lt;p>初期のGNFSでは、$(a, b)$ を $xy$ 平面上に並べて端から順に素数で割っていく「直線篩（Line Sieve）」が使われていました。しかし、これではメモリのあちこちへアクセスするためキャッシュミスが多発し、非常に遅いという弱点がありました。&lt;/p>
&lt;p>そこで、現在の最先端コードでは &lt;strong>「特殊 $q$ 格子篩（Special-q Lattice Sieve）」&lt;/strong> という手法が用いられます。
ある適度に大きな素数 $q$ を固定し、「代数側の値が必ず $q$ で割り切れるような $(a, b)$ のペア」だけを計算対象にします。この条件を満たす $(a, b)$ は平面上の「格子（Lattice）」を形成するため、計算するアドレスのジャンプ幅が一定になり、CPUのL1/L2キャッシュに完璧にフィットします。
この格子篩の導入により、GNFSの計算速度は劇的に向上しました。&lt;/p>
&lt;hr>
&lt;h2 id="5-phase-3-フィルタリングfiltering">5. Phase 3: フィルタリング（Filtering）
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">Filter&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">void&lt;/span> &lt;span class="n">reduce_matrix&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Relation&lt;/span>&lt;span class="o">&amp;gt;&amp;amp;&lt;/span> &lt;span class="n">relations&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 1. Singleton removal (1度しか出現しない素数を持つリレーションの削除)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// 2. Clique merging (疎な行列を密にするためのリレーション結合)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Phase 2で世界中のコンピュータが数ヶ月かけて集めた数億個のリレーション。しかし、これをそのまま次の「連立方程式を解くステップ（行列計算）」に投げ込むと、スーパーコンピュータのメモリがパンクしてしまいます。&lt;/p>
&lt;p>そこで &lt;strong>Filtering（フィルタリング）&lt;/strong> と呼ばれる、行列の超圧縮プロセスが行われます。&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Singleton removal（特異点パージ）&lt;/strong>
ある巨大な素数 $p$ が、数億個のリレーションの中で「たった1回」しか登場しなかったとします。私たちが目指すのは「すべての素数の指数を偶数（2の倍数）にすること」ですから、1回しか登場しない素数は絶対に偶数にできません。
したがって、その素数を含むリレーションは「使い道がないゴミ」として即座に削除（パージ）されます。これが連鎖的に起こることで、数億行あったデータがどんどん削られていきます。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Clique merging（クリークマージ）&lt;/strong>
さらに、特定の素数を共有するリレーション同士を掛け合わせる（足し合わせる）ことで、行の数を減らしつつ、疎な（スカスカな）行列をより密な状態へと圧縮します（グラフ理論のクリーク探索に似た手法を用います）。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>この最適化により、巨大なスパース行列は計算可能なサイズへと劇的に圧縮されます。&lt;/p>
&lt;hr>
&lt;h2 id="6-phase-4-gf2-上の線形代数block-wiedemann法">6. Phase 4: GF(2) 上の線形代数（Block Wiedemann法）
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">LinearAlgebraGF2&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&amp;gt;&lt;/span> &lt;span class="n">solve_nullspace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Relation&lt;/span>&lt;span class="o">&amp;gt;&amp;amp;&lt;/span> &lt;span class="n">relations&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// スパース行列(疎行列)とベクトルの積演算を反復し、
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// M * x = 0 mod 2 となる解ベクトル(カーネル)を複数見つける。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>いよいよ、パズルの核心です。
集めたリレーションを掛け合わせて &lt;strong>「素因数の指数がすべて偶数になる組み合わせ」&lt;/strong> を探します。&lt;/p>
&lt;p>これは数学的には、各素数の指数の「偶数・奇数（つまり0か1）」を要素とする巨大な行列 $M$ と、どのリレーションを使うかを表すベクトル $x$ を用いて、
&lt;strong>$M \cdot x \equiv 0 \pmod 2$&lt;/strong>
となる解ベクトル $x$ （ヌルスペース・カーネル）を求めることに他なりません。&lt;/p>
&lt;p>数百万行 × 数百万列という、とてつもないサイズの行列の連立方程式を解かなければなりません。通常のガウスの消去法では計算量が $O(N^3)$ となり、宇宙が終わるまで計算が終わりません。&lt;/p>
&lt;p>そこで、最先端の実装では &lt;strong>「Block Wiedemann（ブロック・ヴィーデマン）法」&lt;/strong> が採用されています。
これは、行列 $M$ が「非常にスパース（0がほとんど）」であることを利用し、行列とベクトルの掛け算を反復的に行うことで解を導き出すクリロフ部分空間法の一種です。
旧来のBlock Lanczos法と異なり、Block Wiedemann法は計算プロセスを複数のクラスターに完全に分割できるため、現代の分散クラウドコンピューティングやスーパーコンピュータでの並列計算において圧倒的な威力を発揮します。&lt;/p>
&lt;hr>
&lt;h2 id="7-phase-5-代数的平方根algebraic-square-rootと暗号崩壊">7. Phase 5: 代数的平方根（Algebraic Square Root）と暗号崩壊
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">AlgebraicSquareRoot&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">void&lt;/span> &lt;span class="n">compute_and_factor&lt;/span>&lt;span class="p">(...)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 1. 有理側の平方根 V の計算
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">V&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 2. 代数側の平方根 gamma の計算
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">Y&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">factor&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">V&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">Y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// GCD(X-Y, N)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Phase 4の行列計算により、我々は「掛け合わせるとすべての素因数が偶数乗になるリレーションの集合 $S$」を手に入れました。
これにより、有理側と代数側、それぞれの世界で「2乗」を構築することができます。&lt;/p>
&lt;p>有理側は単なる整数の掛け算なので、平方根 $V$ を計算するのは容易です。
&lt;/p>
$$V^2 = \prod_{S} (a - bm)$$
&lt;p>&lt;strong>しかし、本当の地獄は「代数側」にあります。&lt;/strong>
代数体の世界 $\mathbb{Z}[\alpha]$ では、素因数分解の一意性が成り立たないため、イデアルを用いて計算を行ってきました。行列計算で保証されたのは &lt;strong>「イデアルの2乗」になることだけであり、「要素の2乗（$\gamma^2$）」になることは保証されていない&lt;/strong> のです。&lt;/p>
&lt;p>ここには「イデアル類群の障害」と「単数群の障害」という、代数的整数論における強烈な壁が立ち塞がります。
GNFSでは、この壁を打ち破るために &lt;strong>「平方剰余指標（Quadratic Characters）」&lt;/strong> という魔法を使います。
Phase 4の行列に、あらかじめ数十個の特別な素イデアルに対する平方剰余（ルジャンドル記号）の列をこっそり追加しておくのです。これにより、見つかった集合 $S$ は、圧倒的な確率で障害をスルーし、無事に「真の要素の2乗 $\gamma^2$」を形成してくれます。&lt;/p>
&lt;p>$\gamma$ を求める作業（代数的平方根）は、Montgomery法などの非常に複雑なアルゴリズムを用いて計算されます。&lt;/p>
&lt;p>そしてついに、代数側の平方根 $\gamma$ を、環準同型写像 $\phi$ によって現実の世界にワープ（$x$ に $m$ を代入）させ、$Y$ を得ます。
有理側の $V$ をそのまま $X$ と置けば、ついに追い求めた絶対等式が完成します。&lt;/p>
&lt;p>&lt;strong>$$X^2 \equiv Y^2 \pmod N$$&lt;/strong>&lt;/p>
&lt;p>あとは $\gcd(X-Y, N)$ を計算するだけ。0.001秒の処理が走り抜け、非自明な因数が画面に印字された瞬間、難攻不落を誇ったRSA暗号は完全に崩壊します。&lt;/p>
&lt;hr>
&lt;h2 id="結び">結び
&lt;/h2>&lt;p>GNFSは、単なるプログラミングのテクニックではありません。
抽象代数学、環論、イデアル類群といった「純粋数学の深淵」を、スーパーコンピュータの分散アーキテクチャやキャッシュ最適化といった「極限のエンジニアリング」でねじ伏せた、人類の知性の結晶です。&lt;/p>
&lt;p>私たちが何気なく送信しているチャットやクレジットカードの情報は、このような天文学的な数学の攻防の上に守られているのです。&lt;/p>
&lt;p>このC++フレームワークを通じて、最先端の暗号解読アルゴリズムの裏側にある「数学と計算機のロマン」を感じていただければ幸いです。&lt;/p></description></item><item><title>一般数体篩法（GNFS）の真の数学的構造</title><link>http://kenji.blog/p/%E4%B8%80%E8%88%AC%E6%95%B0%E4%BD%93%E7%AF%A9%E6%B3%95gnfs%E3%81%AE%E7%9C%9F%E3%81%AE%E6%95%B0%E5%AD%A6%E7%9A%84%E6%A7%8B%E9%80%A0/</link><pubDate>Sat, 05 Sep 2026 02:26:13 +0900</pubDate><guid>http://kenji.blog/p/%E4%B8%80%E8%88%AC%E6%95%B0%E4%BD%93%E7%AF%A9%E6%B3%95gnfs%E3%81%AE%E7%9C%9F%E3%81%AE%E6%95%B0%E5%AD%A6%E7%9A%84%E6%A7%8B%E9%80%A0/</guid><description>&lt;img src="http://kenji.blog/p/%E4%B8%80%E8%88%AC%E6%95%B0%E4%BD%93%E7%AF%A9%E6%B3%95gnfs%E3%81%AE%E7%9C%9F%E3%81%AE%E6%95%B0%E5%AD%A6%E7%9A%84%E6%A7%8B%E9%80%A0/rsa_encryption_break_1788542156523.jpg" alt="Featured image of post 一般数体篩法（GNFS）の真の数学的構造" />&lt;h1 id="一般数体篩法gnfsの真の数学的構造">一般数体篩法（GNFS）の真の数学的構造
&lt;/h1>&lt;p>GNFSの究極の目的は、$X^2 \equiv Y^2 \pmod N$ となる $X, Y$ を見つけることです。
これを達成するために、数学者たちは &lt;strong>「現実の整数の世界」&lt;/strong> と &lt;strong>「代数体の世界」&lt;/strong> の間に橋を架けました。その橋こそが「準同型写像」です。&lt;/p>
&lt;h2 id="第1段階世界を繋ぐ準同型写像homomorphism">第1段階：世界を繋ぐ「準同型写像（Homomorphism）」
&lt;/h2>&lt;h3 id="1-多項式の選定と根の定義">1. 多項式の選定と根の定義
&lt;/h3>&lt;p>巨大な合成数 $N$ に対し、ある整数 $m$ と多項式 $f(x)$ を選び、$f(m) \equiv 0 \pmod N$ となるようにします。
（例：$N$ を $m$ 進数展開し、その係数から $f(x)$ を作ります。このとき $f(x)$ は有理数体 $\mathbb{Q}$ 上で既約（これ以上因数分解できない）とします）。&lt;/p>
&lt;p>次に、方程式 $f(x) = 0$ の「複素数における根」の一つを $\alpha$ と置きます。
当然、$f(\alpha) = 0$ です。$\alpha$ は整数ではなく、ルートや虚数を含むような複雑な数（代数的数）です。&lt;/p>
&lt;h3 id="2-環ringと準同型写像の構築">2. 環（Ring）と準同型写像の構築
&lt;/h3>&lt;p>ここで、2つの数学的な「環（足し算と掛け算が定義された世界）」を用意します。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>世界A： $\mathbb{Z}[\alpha]$&lt;/strong> （$\alpha$ を含む代数的な整数の環）
$a + b\alpha + c\alpha^2 + \dots$ という形で表される数の世界です。&lt;/li>
&lt;li>&lt;strong>世界B： $\mathbb{Z}/N\mathbb{Z}$&lt;/strong> （$N$ で割った余りの環）
$0$ から $N-1$ までの整数だけで構成される、合同式（モジュロ）の世界です。&lt;/li>
&lt;/ul>
&lt;p>ここで、世界Aから世界Bへ、次のようなマッピング（写像） $\phi$ を定義します。
&lt;strong>$$\phi : \mathbb{Z}[\alpha] \to \mathbb{Z}/N\mathbb{Z}$$&lt;/strong>
&lt;strong>$$\phi(\alpha) = m \pmod N$$&lt;/strong>&lt;/p>
&lt;p>この写像 $\phi$ は、世界Aの変数 $\alpha$ を、そっくりそのまま世界Bの整数 $m$ にすり替える魔法の操作です。
この $\phi$ は &lt;strong>「環準同型写像（Ring Homomorphism）」&lt;/strong> という極めて強力な性質を持っています。
準同型とは、 &lt;strong>「足し算や掛け算の構造を壊さずに、別の世界へワープさせる」&lt;/strong> 性質のことです。つまり、以下の式が成り立ちます。&lt;/p>
&lt;ul>
&lt;li>$\phi(X \times Y) = \phi(X) \times \phi(Y)$&lt;/li>
&lt;li>$\phi(X^2) = \phi(X)^2$&lt;/li>
&lt;/ul>
&lt;p>これが何を意味するか。もし私たちが「世界A（$\alpha$の世界）」で、何か複雑な要素 $\gamma$ の &lt;strong>「2乗（$\gamma^2$）」&lt;/strong> を作ることができれば、それを $\phi$ で「世界B（余りの世界）」にワープさせても、 ** 見事に2乗の形 $\phi(\gamma)^2$ が保たれる** ということです。&lt;/p>
&lt;hr>
&lt;h2 id="第2段階素因数分解の崩壊とイデアルidealの誕生">第2段階：素因数分解の崩壊と「イデアル（Ideal）」の誕生
&lt;/h2>&lt;p>私たちは世界A（$\mathbb{Z}[\alpha]$）の中で、適当な要素 $(a - b\alpha)$ をたくさん集め、それらを掛け合わせて「完全な2乗（平方元）」を作りたいと考えます。
普通なら、集めた $(a - b\alpha)$ をそれぞれ「素因数分解」して、素数の指数がすべて偶数になるように組み合わせ（行列で解く）れば2乗が作れます。&lt;/p>
&lt;p>&lt;strong>しかし、ここで代数学の絶望的な壁が立ちはだかります。&lt;/strong>
$\mathbb{Z}[\alpha]$ のような代数体の世界では、中学で習う &lt;strong>「素因数分解の一意性（どんな数も素数の掛け算でただ1通りに表せる）」が崩壊してしまう&lt;/strong> のです。&lt;/p>
&lt;p>（例：ある代数体の世界では、$6 = 2 \times 3$ であり、同時に $6 = (1+\sqrt{-5}) \times (1-\sqrt{-5})$ となってしまい、どちらが本当の素数か分からなくなります）&lt;/p>
&lt;p>素因数分解が1通りに定まらなければ、「素数の個数を数えて偶数個にする」というパズル（篩法）が原理的に実行できません。&lt;/p>
&lt;h3 id="クンマーとデデキントの救済イデアル">クンマーとデデキントの救済：「イデアル」
&lt;/h3>&lt;p>この崩壊を救ったのが、19世紀の数学者が生み出した &lt;strong>「イデアル（Ideal：理想数）」&lt;/strong> という概念です。
要素そのものではなく、その要素が生成する「倍数の集合（イデアル）」を考えることで、再び素因数分解を可能にしたのです。&lt;/p>
&lt;p>代数体の整数環 $\mathcal{O}_K$（$\mathbb{Z}[\alpha]$ を含むより完全な環）において、要素は一意に素因数分解できなくても、 &lt;strong>「イデアルは必ず『素イデアル（$\mathfrak{p}$）』の積としてただ1通りに素因数分解できる」&lt;/strong> ことが証明されています。&lt;/p>
&lt;p>したがってGNFSでは、要素 $(a - b\alpha)$ そのものを分解するのではなく、それが生成する &lt;strong>単項イデアル $\langle a - b\alpha \rangle$ を素イデアル分解&lt;/strong> します。&lt;/p>
&lt;hr>
&lt;h2 id="第3段階ノルムnormと2つの篩sieve">第3段階：ノルム（Norm）と2つの篩（Sieve）
&lt;/h2>&lt;p>では、イデアル $\langle a - b\alpha \rangle$ がどんな素イデアルに分解されるか、どうやって知るのでしょうか？
ここで &lt;strong>「ノルム（Norm）」&lt;/strong> という関数を使います。ノルムとは、代数体の複雑な要素を「普通の現実の整数 $\mathbb{Z}$」に変換する関数です。&lt;/p>
&lt;p>要素 $(a - b\alpha)$ のノルムは、$b^d f(a/b)$ という簡単な多項式の計算で求まります（$d$ は $f(x)$ の次数）。&lt;/p>
&lt;p>代数的な定理により、 &lt;strong>「あるイデアルのノルムが小さな素数で完全に分解できる（滑らかである）ならば、その元のイデアルも小さな素イデアルで完全に分解できる」&lt;/strong> ことが分かっています。&lt;/p>
&lt;p>そこでGNFSは、大量の整数のペア $(a, b)$ に対して、次の2つを同時に計算し、両方が「滑らかな数」になるペアだけを収集します。&lt;/p>
&lt;ol>
&lt;li>&lt;strong>有理篩（Rational Sieve）&lt;/strong>： $a - bm$ （現実の世界の値）&lt;/li>
&lt;li>&lt;strong>代数篩（Algebraic Sieve）&lt;/strong>： $b^d f(a/b)$ （代数体の世界でのノルム）&lt;/li>
&lt;/ol>
&lt;p>両方が滑らかなペア $(a, b)$ を数千万個集め、イデアルの素因数分解データ（素イデアルが何個含まれているか）を巨大な行列（GF(2)上の線形代数）として解き、「掛け合わせると全ての素イデアルの指数が偶数になる」ようなペアの集合 $S$ を見つけます。&lt;/p>
&lt;hr>
&lt;h2 id="第4段階立ちはだかる2つの障害とイデアル類群">第4段階：立ちはだかる2つの「障害」とイデアル類群
&lt;/h2>&lt;p>行列計算により、集合 $S$ に属する $(a - b\alpha)$ のイデアルをすべて掛け合わせると、あるイデアル $I$ の2乗になることが分かりました。
&lt;/p>
$$\prod_{S} \langle a - b\alpha \rangle = I^2$$
&lt;p>&lt;strong>しかし、まだ終わりません。GNFSにおける最も深く、最も困難な数学の壁がここにあります。&lt;/strong>&lt;/p>
&lt;p>私たちが最後に欲しいのは、「イデアルの2乗」ではなく、写像 $\phi$ に代入するための &lt;strong>「要素の2乗（$\gamma^2$）」&lt;/strong> です。
イデアルの2乗になったからといって、要素自体が2乗になっているとは限らないのです。ここには &lt;strong>2つの強烈な数学的障害（Obstruction）&lt;/strong> が存在します。&lt;/p>
&lt;h3 id="障害イデアル類群ideal-class-groupの壁">障害①：イデアル類群（Ideal Class Group）の壁
&lt;/h3>&lt;p>イデアル $I$ は、必ずしも「1つの要素で生成されるイデアル（単項イデアル）」とは限りません。
単項イデアルではないイデアルから、具体的な要素 $\gamma$ を取り出すことは不可能です。&lt;/p>
&lt;p>ここで &lt;strong>「イデアル類群（Class Group, $Cl_K$）」&lt;/strong> という概念が登場します。イデアル類群とは、「その代数体の世界に、単項イデアルではないイデアルがどれくらい存在するか（素因数分解の一意性がどれくらい壊れているか）」を測る群です。
$\prod \langle a - b\alpha \rangle$ が $I^2$ になったとしても、$I$ がイデアル類群において単位元（単項イデアル）でなければ、要素の2乗に引き戻すことができません。&lt;/p>
&lt;h3 id="障害単数群unit-groupの壁">障害②：単数群（Unit Group）の壁
&lt;/h3>&lt;p>仮に運良く $I$ が単項イデアル $\langle \gamma \rangle$ だったとしましょう。
すると、$\prod \langle a - b\alpha \rangle = \langle \gamma^2 \rangle$ となります。
「よし、要素も2乗だ！」と思うかもしれませんが、大間違いです。&lt;/p>
&lt;p>イデアル（倍数の集合）が等しいということは、要素が完全に等しいことを意味しません。必ず &lt;strong>「単数（Unit：逆数も整数になるような数。1 や -1 など）」&lt;/strong> のズレが生じます。
つまり、実際の要素の等式は次のようになります。
&lt;/p>
$$\prod_{S} (a - b\alpha) = u \cdot \gamma^2$$
&lt;p>
（$u$ は単数群 $U_K$ の要素）&lt;/p>
&lt;p>この単数 $u$ 自体が何かの2乗（平方元）でなければ、左辺は絶対に「完全な要素の2乗」にはなれません。&lt;/p>
&lt;hr>
&lt;h2 id="第5段階アドレマンの魔法平方剰余指標quadratic-characters">第5段階：アドレマンの魔法「平方剰余指標（Quadratic Characters）」
&lt;/h2>&lt;p>イデアル類群の障害と、単数群の障害。この2つをどうやって乗り越えるのか？
ここで、暗号学者レナード・アドレマン（RSAの&amp;quot;A&amp;quot;）らが導入した天才的な手法 &lt;strong>「平方剰余指標（Quadratic Characters）」&lt;/strong> が登場します。&lt;/p>
&lt;p>「ある要素が代数体の中で完全に2乗になっているか？」を判定するために、ルジャンドル記号（平方剰余）の代数体バージョンを使います。
先ほどの巨大な行列（素イデアルの個数を偶数にするためのパズル）に、 &lt;strong>「いくつかの特別な素イデアル $\mathfrak{q}$ に対する平方剰余指標もすべて $1$（偶数）になる」という追加の条件（列）を数十個ほどこっそり付け足す&lt;/strong> のです。&lt;/p>
&lt;p>行列計算によってこの追加条件すらも満たす集合 $S$ を見つけたとき、代数的整数論の深い定理により、 &lt;strong>「イデアル類群の障害も、単数群の障害も、圧倒的な確率で自然に消滅する」&lt;/strong> ことが保証されます。&lt;/p>
&lt;p>これにより、ついに私たちは真の等式を手に入れます。
&lt;/p>
$$\prod_{S} (a - b\alpha) = \gamma^2$$
&lt;hr>
&lt;h2 id="最終段階世界の融合と暗号崩壊">最終段階：世界の融合と暗号崩壊
&lt;/h2>&lt;p>ついにパズルのすべてのピースが揃いました。&lt;/p>
&lt;p>&lt;strong>【代数体の世界（世界A）の要素】&lt;/strong>
$\gamma^2 = \prod (a - b\alpha)$
（これを平方根アルゴリズムを使って $\gamma$ を求めます）&lt;/p>
&lt;p>&lt;strong>【現実の世界（有理数の世界）の要素】&lt;/strong>
$V^2 = \prod (a - bm)$
（こちらは単なる整数の掛け算なので、普通に平方根 $V$ が求まります）&lt;/p>
&lt;p>さあ、一番最初に作った魔法の橋、 &lt;strong>準同型写像 $\phi$&lt;/strong> の出番です。
世界Aの要素 $\gamma$ を、$\phi$（$\alpha$ に $m$ を代入する写像）を使って、世界B（$N$の余りの世界）にワープさせます。
&lt;/p>
$$Y = \phi(\gamma) \pmod N$$
&lt;p>一方、現実の世界で作った $V$ を、そのまま余りの世界に持っていき $X$ とします。
&lt;/p>
$$X = V \pmod N$$
&lt;p>準同型写像の「構造を保つ」性質により、世界Aで成り立っていた2乗の関係は、世界B（モジュロ $N$ の世界）でも完全に保存されています。
さらに、元のペア $(a, b)$ は $a - b\alpha$ と $a - bm$ という形で対応して作られていたため、この $X$ と $Y$ はモジュロ $N$ の世界で激突し、次の絶対的な等式を生み出します。&lt;/p>
&lt;p>&lt;strong>$$X^2 \equiv Y^2 \pmod N$$&lt;/strong>&lt;/p>
&lt;p>あとは、この $X$ と $Y$ が自明な解（$X \equiv \pm Y$）でないことを祈りながら、
&lt;strong>$\gcd(X - Y, N)$&lt;/strong> を計算します。&lt;/p>
&lt;p>非自明な解であれば、ユークリッドの互除法が0.001秒で走り抜け、RSA暗号の心臓部である秘密の素数 $p$ と $q$ が出力画面に印字されます。&lt;/p>
&lt;hr>
&lt;p>これが、現代数学の粋を集めた &lt;strong>「一般数体篩法（GNFS）」の完全な姿&lt;/strong> です。&lt;/p></description></item><item><title>インターネットの暗号を破る人類最強の数学「一般数体篩法（GNFS）」とは？</title><link>http://kenji.blog/p/%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%8D%E3%83%83%E3%83%88%E3%81%AE%E6%9A%97%E5%8F%B7%E3%82%92%E7%A0%B4%E3%82%8B%E4%BA%BA%E9%A1%9E%E6%9C%80%E5%BC%B7%E3%81%AE%E6%95%B0%E5%AD%A6%E4%B8%80%E8%88%AC%E6%95%B0%E4%BD%93%E7%AF%A9%E6%B3%95gnfs%E3%81%A8%E3%81%AF/</link><pubDate>Sat, 05 Sep 2026 02:09:08 +0900</pubDate><guid>http://kenji.blog/p/%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%8D%E3%83%83%E3%83%88%E3%81%AE%E6%9A%97%E5%8F%B7%E3%82%92%E7%A0%B4%E3%82%8B%E4%BA%BA%E9%A1%9E%E6%9C%80%E5%BC%B7%E3%81%AE%E6%95%B0%E5%AD%A6%E4%B8%80%E8%88%AC%E6%95%B0%E4%BD%93%E7%AF%A9%E6%B3%95gnfs%E3%81%A8%E3%81%AF/</guid><description>&lt;img src="http://kenji.blog/p/%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%8D%E3%83%83%E3%83%88%E3%81%AE%E6%9A%97%E5%8F%B7%E3%82%92%E7%A0%B4%E3%82%8B%E4%BA%BA%E9%A1%9E%E6%9C%80%E5%BC%B7%E3%81%AE%E6%95%B0%E5%AD%A6%E4%B8%80%E8%88%AC%E6%95%B0%E4%BD%93%E7%AF%A9%E6%B3%95gnfs%E3%81%A8%E3%81%AF/gnfs_two_worlds_1788542142485.jpg" alt="Featured image of post インターネットの暗号を破る人類最強の数学「一般数体篩法（GNFS）」とは？" />&lt;h1 id="インターネットの暗号を破る人類最強の数学一般数体篩法gnfsとは">インターネットの暗号を破る人類最強の数学「一般数体篩法（GNFS）」とは？
&lt;/h1>&lt;p>私たちが毎日使っているインターネット。LINEのメッセージやYouTube、Amazonでの買い物など、すべての通信は「暗号」によって守られています。
現在、世界中で最も使われている暗号の代表が「RSA暗号」です。&lt;/p>
&lt;p>RSA暗号の守りの要（かなめ）は、非常にシンプルです。それは &lt;strong>「巨大な数の素因数分解は、コンピュータでも解けない」&lt;/strong> という数学の性質を利用していること。
たとえば、「15」なら「3 × 5」とすぐに分かりますが、これが「270桁の数字」になった瞬間、世界中のスーパーコンピュータを束ねても解くのに数億年かかってしまいます。&lt;/p>
&lt;p>しかし、数学者たちも黙ってはいません。この鉄壁の暗号を打ち破るために、人類は &lt;strong>「一般数体篩法（GNFS：General Number Field Sieve）」&lt;/strong> という、魔法のようなアルゴリズム（計算手順）を生み出しました。&lt;/p>
&lt;p>この記事では、専門用語を一切使わず、 &lt;strong>中学校で習う数学（素因数分解、文字式、最大公約数）&lt;/strong> の知識だけで、この「人類最強のアルゴリズム」が暗号を破るカラクリをステップごとに完全解説します！&lt;/p>
&lt;hr>
&lt;h2 id="第1章暗号解読のゴールは中学3年の公式">第1章：暗号解読のゴールは「中学3年の公式」
&lt;/h2>&lt;p>巨大な素因数分解に立ち向かうための最大の必殺技。それは、中学3年生で習うこの公式です。&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>$X^2 - Y^2 = (X + Y)(X - Y)$&lt;/strong>&lt;/p>
&lt;/blockquote>
&lt;p>「えっ、こんな基礎的な公式で暗号が破れるの？」と思うかもしれません。しかし、これこそがすべてを解き明かすマスターキーなのです。&lt;/p>
&lt;p>暗号を破るための最大の目標は、巨大な数 $N$ に対して、
&lt;strong>「$X^2$ と $Y^2$ を $N$ で割った余りが同じになる数（$X$ と $Y$）」&lt;/strong> を見つけることです。&lt;/p>
&lt;h3 id="なぜ余りが同じだと暗号が解けるのか">なぜ「余りが同じ」だと暗号が解けるのか？
&lt;/h3>&lt;p>ある2つの数、$X^2$ と $Y^2$ の「$N$ で割った余りが同じ」だとします。
余りが同じということは、 &lt;strong>引き算をした「$X^2 - Y^2$」は、必ず $N$ でピッタリ割り切れる（$N$ の倍数になる）&lt;/strong> という法則があります。&lt;/p>
&lt;p>ここで、暗号に使われる巨大な数 $N$ は、2つの秘密の素数（$p$ と $q$）の掛け算でできているとしましょう（$N = p \times q$）。&lt;/p>
&lt;p>$X^2 - Y^2$ を因数分解すると &lt;strong>$(X - Y)(X + Y)$&lt;/strong> になります。
これが $N$ の倍数であるということは、この掛け算のどこかに、秘密の素数 $p$ と $q$ が隠れているということです。&lt;/p>
&lt;p>ここで奇跡が起きます。
2つの素数 $p$ と $q$ が、 &lt;strong>「$p$ は $(X - Y)$ の部屋へ」「$q$ は $(X + Y)$ の部屋へ」&lt;/strong> と、別々の部屋に分かれて入ってくれる確率が、数学的に ** 50%（2分の1）** あるのです。&lt;/p>
&lt;p>素数 $p$ だけが $(X - Y)$ の部屋に入った状態で、$(X - Y)$ と $N$ の &lt;strong>「最大公約数（共通する一番大きな部品）」&lt;/strong> を計算してみましょう。&lt;/p>
&lt;ul>
&lt;li>$(X - Y)$ の中身 ＝ $p \times$ 何かの数&lt;/li>
&lt;li>$N$ の中身 ＝ $p \times q$
共通している部品は &lt;strong>「$p$」&lt;/strong> しかありませんよね！&lt;/li>
&lt;/ul>
&lt;p>つまり、最大公約数を計算した瞬間、隠れていた素数 $p$ がポロッとこぼれ落ち、暗号が完全に解読されてしまうのです。（※最大公約数は「ユークリッドの互除法」を使えば、スマホでも一瞬で計算できます）&lt;/p>
&lt;p>&lt;strong>【ちょっとコラム：なぜ2乗なの？3乗や2倍じゃダメ？】&lt;/strong>&lt;/p>
&lt;blockquote>
&lt;p>「$2X - 2Y$」だと $2(X - Y)$ になり、部屋が1つしかないので素数を引き離せません。「$X^3 - Y^3$」だと部屋の大きさがアンバランスになり、計算がムダに重くなります。素数を2つに引き離すには、美しく2つの部屋に分かれる「2乗」が一番コスパが良いのです。&lt;/p>
&lt;/blockquote>
&lt;hr>
&lt;h2 id="第2章xとyをどう探す素数カード集めパズル">第2章：XとYをどう探す？「素数カード集めパズル」
&lt;/h2>&lt;p>ゴールは分かりました。しかし、「余りが同じになる $X^2$ と $Y^2$」を当てずっぽうで探しても、宇宙の寿命が終わるまで見つかりません。
そこで、数学者たちは &lt;strong>「素数カード集めパズル」&lt;/strong> という天才的な方法を思いつきました。&lt;/p>
&lt;h3 id="step-1砂金滑らかな数だけをザルで集める">Step 1：砂金（滑らかな数）だけをザルで集める
&lt;/h3>&lt;p>まず、適当な数 $Z$ を用意し、2乗して $N$ で割った余り $W$ を計算します。
（$Z^2 = W$ の余りの世界）&lt;/p>
&lt;p>出てきた余り $W$ を素因数分解します。ここで、 &lt;strong>「2, 3, 5, 7などの小さな素数だけでできている $W$」&lt;/strong> が出たときだけ、その式を「アタリのカード」として残し、大きな素数が混ざっていたら捨てます。
川で大きな石をザル（ふるい）で捨てて、砂金だけを集めるような作業です。&lt;/p>
&lt;h3 id="step-2全部偶数個にするパズル">Step 2：全部「偶数個」にするパズル
&lt;/h3>&lt;p>たとえば、以下の3枚の砂金カードが集まったとします。&lt;/p>
&lt;ul>
&lt;li>カードA： $Z_1^2 = 2^3 \times 3^1$&lt;/li>
&lt;li>カードB： $Z_2^2 = 2^1 \times 5^1$&lt;/li>
&lt;li>カードC： $Z_3^2 = 3^1 \times 5^1$&lt;/li>
&lt;/ul>
&lt;p>これを全部掛け合わせてみましょう。
右側は $(2^3 \times 3^1) \times (2^1 \times 5^1) \times (3^1 \times 5^1)$ となり、
まとめて整理すると &lt;strong>「$2^4 \times 3^2 \times 5^2$」&lt;/strong> になります。&lt;/p>
&lt;p>なんと、素数の個数が「4個、2個、2個」と、 &lt;strong>すべて偶数個&lt;/strong> になりました！
すべて偶数個ということは、全体を半分の個数にすれば「何かの2乗」になります。
つまり、$(2^2 \times 3^1 \times 5^1)^2 = (60)^2$ です。&lt;/p>
&lt;p>左側は $(Z_1 \times Z_2 \times Z_3)^2$ なので、これでついに、
&lt;strong>$X = (Z_1 \times Z_2 \times Z_3)$&lt;/strong>
&lt;strong>$Y = 60$&lt;/strong>
という、待ちに待った「$X^2 = Y^2$」のペアが完成したのです！&lt;/p>
&lt;p>コンピュータにとって、素数の個数を「偶数か奇数か（0か1か）」で計算するパズルは非常に得意なので、この方法なら高速に $X$ と $Y$ を見つけることができます。&lt;/p>
&lt;hr>
&lt;h2 id="第3章立ちはだかる絶望の壁">第3章：立ちはだかる絶望の壁
&lt;/h2>&lt;p>これでどんな暗号も解ける！……と思いきや、大問題が発生します。
暗号の数字 $N$ が「100桁」くらいまでならこの方法（二次篩法といいます）で解けるのですが、$N$ が「200桁、300桁」になると、計算の途中で出てくる $W$ がデカくなりすぎます。&lt;/p>
&lt;p>数字がデカすぎると、「小さな素数だけでできている数（砂金）」がパッタリと出なくなってしまいます。砂漠でコンタクトレンズを探すよりも難しくなり、パズルを解くためのカードが全く集まらなくなってしまうのです。&lt;/p>
&lt;p>ここでついに、人類の最終兵器 &lt;strong>「一般数体篩法（GNFS）」&lt;/strong> が登場します。&lt;/p>
&lt;hr>
&lt;h2 id="第4章人類最強のアイディア2つの世界を作る">第4章：人類最強のアイディア「2つの世界」を作る
&lt;/h2>&lt;p>GNFSの天才的な発想は、 &lt;strong>「現実の世界だけで計算するから数字がデカくなる。なら、多項式（文字式）を使った『裏の世界』を作って、計算の重さを2つに分散させよう」&lt;/strong> というものです。&lt;/p>
&lt;h3 id="文字式の魔法">文字式の魔法
&lt;/h3>&lt;p>GNFSは、巨大な数 $N$ をベースとなる数 $m$ を使って、文字式に変換します。
たとえば $N=100$ なら、$m=4$ として $100 = 4^3 + 2(4^2) + 4$。
これを文字 $x$ を使って &lt;strong>$f(x) = x^3 + 2x^2 + x$&lt;/strong> という式（裏の世界）にします。&lt;/p>
&lt;p>この式の面白いところは、 &lt;strong>「文字 $x$ に $m$（上の例なら4）を代入すれば、いつでも現実の数 $N$ にワープして戻ってこれる」&lt;/strong> という性質を持っていることです。&lt;/p>
&lt;h3 id="2つの世界で同時に砂金探し">2つの世界で同時に砂金探し
&lt;/h3>&lt;p>GNFSは、適当な整数のペア $(a, b)$ をたくさん作り、次の2つの計算を同時に行います。&lt;/p>
&lt;ol>
&lt;li>&lt;strong>現実の世界&lt;/strong>： $a - b \times m$&lt;/li>
&lt;li>&lt;strong>文字式の世界&lt;/strong>： $a - b \times x$ を文字式のルールで計算した値&lt;/li>
&lt;/ol>
&lt;p>問題を2つの世界に分けたことで、扱う数字のサイズが劇的に小さく（軽く）なります。巨大な岩を2つに割って、扱いやすい石コロにしたイメージです。&lt;/p>
&lt;p>そして、 &lt;strong>「現実の世界でも、文字式の世界でも、両方とも『小さな素数だけでできている（砂金）』」&lt;/strong> という奇跡のペア $(a, b)$ だけをザル（篩：ふるい）でより分けて集めます。これが「数体篩法」という名前の由来です。&lt;/p>
&lt;h3 id="ついに暗号が破れる瞬間">ついに暗号が破れる瞬間
&lt;/h3>&lt;p>両方の世界から数千万枚の「砂金カード」が集まったら、スーパーコンピュータの巨大な行列計算を使って、第2章でやった「素数の個数が全部偶数になる組み合わせ」を見つけ出します。&lt;/p>
&lt;p>組み合わせが見つかったら、&lt;/p>
&lt;ul>
&lt;li>現実の世界でできた2乗の数を &lt;strong>$X^2$&lt;/strong>&lt;/li>
&lt;li>文字式の世界でできた2乗の式を &lt;strong>$Y(x)^2$&lt;/strong> とします。&lt;/li>
&lt;/ul>
&lt;p>最後に、文字式の $Y(x)$ の $x$ に $m$ を代入し、現実の世界にワープさせて合流させます。
すると、数学の魔法のように &lt;strong>「$X^2$ と $Y^2$ の余りが同じになる」&lt;/strong> という状態が厳密に完成するのです！&lt;/p>
&lt;p>あとは第1章の通り、$X - Y$ と $N$ の最大公約数を計算すれば、難攻不落のRSA暗号は音を立てて崩れ去り、秘密の素数が姿を現します。&lt;/p>
&lt;hr>
&lt;h2 id="おわりに数学は終わらない">おわりに：数学は終わらない
&lt;/h2>&lt;p>「よし、GNFSを使えばどんな暗号も破れるんだな！」と思ったかもしれません。
しかし、RSA暗号も負けていません。現在のインターネットで使われているのは「RSA-2048（約617桁）」というバケモノのような巨大数です。&lt;/p>
&lt;p>GNFSがいかに人類最強のアルゴリズムとはいえ、270桁（RSA-270）を解くのにすら、世界中のコンピュータを繋いでも数千年、数万年かかると言われています。今のところ、私たちのLINEや銀行のデータは安全です。&lt;/p>
&lt;p>しかし、もし &lt;strong>「どんな巨大な数でも一瞬で $X$ と $Y$ を見つける魔法」&lt;/strong> が現れたらどうなるでしょうか？
実は、それに最も近い存在が現在開発中の &lt;strong>「量子コンピュータ（ショアのアルゴリズム）」&lt;/strong> です。量子力学の波の性質を使えば、面倒なカード集めパズルを無視して、一発で答えを引き当てることができると数学的に証明されています。&lt;/p>
&lt;p>暗号を作る人（防御）と、暗号を破るアルゴリズムを作る人（攻撃）の果てしない知恵比べ。
中学校で習う「素因数分解」や「文字式」が、実は世界のセキュリティの最前線でバチバチに戦っている武器だと知ると、少しだけ数学の授業が面白く見えてきませんか？&lt;/p>
&lt;p>未来の最強アルゴリズムを発見するのは、この記事を読んでいるあなたかもしれません！&lt;/p>
&lt;hr>
&lt;p>&lt;em>(※本記事は、暗号解読の数学的魅力を中学生向けに概念化したものです。実際のGNFSは、代数体のイデアル類群や準同型写像などの高度な大学数学を用いて厳密に計算されています)&lt;/em>&lt;/p></description></item><item><title>ケプラー予想をわかりやすく解説</title><link>http://kenji.blog/p/%E3%82%B1%E3%83%97%E3%83%A9%E3%83%BC%E4%BA%88%E6%83%B3%E3%82%92%E3%82%8F%E3%81%8B%E3%82%8A%E3%82%84%E3%81%99%E3%81%8F%E8%A7%A3%E8%AA%AC/</link><pubDate>Mon, 21 Jul 2025 22:53:03 +0900</pubDate><guid>http://kenji.blog/p/%E3%82%B1%E3%83%97%E3%83%A9%E3%83%BC%E4%BA%88%E6%83%B3%E3%82%92%E3%82%8F%E3%81%8B%E3%82%8A%E3%82%84%E3%81%99%E3%81%8F%E8%A7%A3%E8%AA%AC/</guid><description>&lt;img src="http://kenji.blog/p/%E3%82%B1%E3%83%97%E3%83%A9%E3%83%BC%E4%BA%88%E6%83%B3%E3%82%92%E3%82%8F%E3%81%8B%E3%82%8A%E3%82%84%E3%81%99%E3%81%8F%E8%A7%A3%E8%AA%AC/img.png" alt="Featured image of post ケプラー予想をわかりやすく解説" />&lt;h1 id="ケプラー予想をわかりやすく解説スイカを一番ぎっしり詰める方法">ケプラー予想をわかりやすく解説！〜スイカを一番ぎっしり詰める方法〜
&lt;/h1>&lt;p>こんにちは、kenjiです！&lt;/p>
&lt;p>今日は「ケプラー予想」っていう、ちょっと難しそうな名前の数学の話を、できるだけわかりやすく説明してみたいと思います。&lt;/p>
&lt;p>一見、めちゃくちゃマニアックな話なんですが、「スイカを箱にぎっしり詰めるにはどうしたらいいか？」という、わりと身近な問題でもあるんですよね。コンビニの冷蔵庫にも関係があるし、荷物の積み方にも関係ある。&lt;/p>
&lt;p>そして、数学の世界では、これがなんと &lt;strong>400年以上も証明できなかった&lt;/strong> という、超・ロマンある話でもあります。&lt;/p>
&lt;p>ではいってみましょう！&lt;/p>
&lt;hr>
&lt;h2 id="そもそもケプラーって誰">そもそもケプラーって誰？
&lt;/h2>&lt;p>まず、「ケプラー予想」の「ケプラー」って誰？という話なんですが。&lt;/p>
&lt;p>これは、&lt;strong>ヨハネス・ケプラー（Johannes Kepler）&lt;/strong> というドイツの天文学者・数学者の名前です。&lt;/p>
&lt;p>この人、めちゃくちゃすごい人でして。
たとえば、惑星の軌道が楕円（だえん）になっているってことを発見したのもこの人。今では当たり前の知識ですが、当時（1600年頃）は地動説すらちゃんと信じられてなかった時代なんですよ。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>ガリレオ＝観測の天才&lt;/strong>&lt;/li>
&lt;li>&lt;strong>ケプラー＝数式で宇宙を説明した天才&lt;/strong>&lt;/li>
&lt;li>&lt;strong>ニュートン＝その理論を物理法則にまとめた超天才&lt;/strong>&lt;/li>
&lt;/ul>
&lt;p>みたいな位置づけで、ケプラーは「数式で宇宙を語る」っていう先駆者でした。&lt;/p>
&lt;p>で、そんな彼が、ある時こう言い出します。&lt;/p>
&lt;hr>
&lt;h2 id="ケプラー予想ってなに">ケプラー予想ってなに？
&lt;/h2>&lt;p>「ケプラー予想」とは、簡単にいうと、こういう話です。&lt;/p>
&lt;hr>
&lt;blockquote>
&lt;p>&lt;strong>同じ大きさの球（スイカやオレンジ）を箱に詰めるとき、どの並べ方が一番ぎっしり詰められるのか？&lt;/strong>&lt;/p>
&lt;/blockquote>
&lt;hr>
&lt;p>っていう問題。&lt;/p>
&lt;p>で、ケプラーが1600年代に予想したのが&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>オレンジを八百屋で並べるみたいに、三角形っぽく積むのが一番効率いいんじゃない？&lt;/strong>&lt;/p>
&lt;/blockquote>
&lt;p>ってこと。&lt;/p>
&lt;p>これを数学っぽくいうと、&lt;strong>「最密充填問題（さいみつじゅうてんもんだい）」&lt;/strong> といって、球を空間に一番密に敷き詰める方法を探す問題なんですね。&lt;/p>
&lt;p>ケプラーは、&lt;strong>「面心立方構造（FCC）」&lt;/strong> っていう並べ方（スイカを三角形に積むような感じ）が一番効率がいいと予想しました。&lt;/p>
&lt;p>で、これ、みんな「たしかにそれっぽいね〜」とは思ってたんですが、数学的に「絶対にこれが一番だ！」って証明するのがめちゃくちゃ難しかったんです。&lt;/p>
&lt;hr>
&lt;h2 id="証明まで400年">証明まで400年！？！
&lt;/h2>&lt;p>じゃあ、実際にそれが証明されたのはいつかというと…&lt;/p>
&lt;p>なんと &lt;strong>1998年〜2005年ごろ&lt;/strong> です。
つまり、&lt;strong>400年近くも誰も証明できなかった&lt;/strong> んですね。やばすぎる。&lt;/p>
&lt;p>しかも、証明したのはアメリカの数学者 &lt;strong>トーマス・ヘイルズ（Thomas Hales）&lt;/strong> という人。&lt;/p>
&lt;p>この人、手計算だけじゃ無理と判断して、&lt;strong>コンピューターを使って証明&lt;/strong> しました。
ただ、その証明があまりに複雑すぎて、人間がちゃんとチェックできない！という問題が発生。&lt;/p>
&lt;p>そこで、数学の世界でも「じゃあ、コンピューターで証明したのって本当に信用できるの？」という大論争が起きました。&lt;/p>
&lt;p>結局、「コンピューターを含めて厳密に検証したよ！」という証明（正式には「形式化証明」といいます）が完了したのは &lt;strong>2014年&lt;/strong>。&lt;/p>
&lt;p>つまり、ケプラーの直感が &lt;strong>正しかったと証明されるまで、400年以上&lt;/strong> かかったというわけです。すごいロマン。&lt;/p>
&lt;hr>
&lt;h2 id="実生活でもめっちゃ使われてる">実生活でもめっちゃ使われてる
&lt;/h2>&lt;p>「球をどうやって並べるか」なんて、数学オタクだけの話かと思いきや、実は超実用的です。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>コンビニの冷蔵庫でドリンクを効率よく詰める&lt;/strong>&lt;/li>
&lt;li>&lt;strong>缶詰を輸送用パレットに積むとき&lt;/strong>&lt;/li>
&lt;li>&lt;strong>通信（デジタル信号の圧縮とか）にも応用されている&lt;/strong>&lt;/li>
&lt;li>&lt;strong>3Dプリンターや結晶構造の設計にも使われる&lt;/strong>&lt;/li>
&lt;/ul>
&lt;p>などなど、実は僕たちの生活の裏にゴリゴリ使われてる理論です。&lt;/p>
&lt;hr>
&lt;h2 id="まとめ人間の直感ってすごい">まとめ：人間の直感ってすごい
&lt;/h2>&lt;p>というわけで、まとめます。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>ケプラー予想&lt;/strong>＝球を一番ぎっしり詰めるにはどうする？という問題&lt;/li>
&lt;li>&lt;strong>ケプラーさん&lt;/strong>＝惑星の軌道を発見した数学・天文学者&lt;/li>
&lt;li>&lt;strong>予想されたのは1600年代！でも証明されたのは2000年代！&lt;/strong>&lt;/li>
&lt;li>&lt;strong>実生活にもめっちゃ応用されてる！&lt;/strong>&lt;/li>
&lt;/ul>
&lt;p>そしてなにより面白いのは、
&lt;strong>「八百屋さんが感覚でやってた積み方が、数学的にも最強だった」&lt;/strong> という点。&lt;/p>
&lt;p>つまり、&lt;strong>人間の直感ってすごい&lt;/strong>。
そして、&lt;strong>それを証明するのに400年かかることもある&lt;/strong> っていうのが、なんともロマンのある話ですよね。&lt;/p>
&lt;hr>
&lt;p>興味を持った方は、ぜひ「トーマス・ヘイルズ」「形式化証明」「Sphere Packing」なんかで調べてみてください。深掘りするとめちゃくちゃ面白いです。&lt;/p>
&lt;p>ではでは！&lt;/p>
&lt;hr>
&lt;p>[PR]&lt;/p>
&lt;div style="background:#fff;width:120px;height:215px;box-sizing:border-box;border:1px solid #ccc;display:flex;flex-direction:column;justify-content:flex-start;align-items:center;">&lt;div style="line-height:0;">&lt;img src="https://static.jp.mercari.com/assets/img/common/jp/logo_horizontal.png" width="105">&lt;/div>&lt;a href="https://jp.mercari.com/item/m71496725612?afid=1916658352" style="width:100px;height:100px;background:#eee;" target="_blank">&lt;img src="https://ambassador-system.mercari.com/v1/i?id=m71496725612&amp;svc=m" style="line-height:0;width:100px;height:100px;object-fit:contain;"/>&lt;/a>&lt;div style="padding:12px 0;width:100%;text-align:center;">&lt;a href="https://jp.mercari.com/item/m71496725612?afid=1916658352" style="width:100px;height:32px;background-color:#E32B36;border-radius:4px;line-height:14px;text-align:center;color:#fff;font-weight:bold;border:0;font-size:12px;display:inline-flex;justify-content:center;align-items:center;" target="_blank">今すぐ購入&lt;/a>&lt;/div>&lt;/div></description></item><item><title>コラッツ予想</title><link>http://kenji.blog/p/%E3%82%B3%E3%83%A9%E3%83%83%E3%83%84%E4%BA%88%E6%83%B3/</link><pubDate>Tue, 15 Jul 2025 18:03:03 +0900</pubDate><guid>http://kenji.blog/p/%E3%82%B3%E3%83%A9%E3%83%83%E3%83%84%E4%BA%88%E6%83%B3/</guid><description>&lt;img src="http://kenji.blog/p/%E3%82%B3%E3%83%A9%E3%83%83%E3%83%84%E4%BA%88%E6%83%B3/img.png" alt="Featured image of post コラッツ予想" />&lt;h1 id="どんな数字でも最後は1になるってほんとコラッツ予想を遊んでみた">「どんな数字でも最後は1になる」ってほんと？──コラッツ予想を遊んでみた
&lt;/h1>&lt;p>こんにちは！kenjiです。&lt;/p>
&lt;p>突然ですが、「どんな数字でも最終的に1になるルール」って聞いたら、
ちょっと不思議じゃないですか？&lt;/p>
&lt;blockquote>
&lt;p>例えば、19とか、87とか、1000000でも。
適当なルールに従って数をいじっていくと、なぜか最後は「1」に収束する。&lt;/p>
&lt;/blockquote>
&lt;p>そんな夢みたいな話が、&lt;strong>コラッツ予想（Collatz Conjecture）&lt;/strong> です。&lt;/p>
&lt;hr>
&lt;h2 id="そもそもコラッツ予想ってなに">そもそも、コラッツ予想ってなに？
&lt;/h2>&lt;p>まずはルールを紹介します。&lt;/p>
&lt;ul>
&lt;li>
&lt;p>スタート：任意の &lt;strong>正の整数&lt;/strong> を選びます&lt;/p>
&lt;/li>
&lt;li>
&lt;p>操作：&lt;/p>
&lt;ul>
&lt;li>偶数なら → 半分にする（n → n / 2）&lt;/li>
&lt;li>奇数なら → 3倍して1足す（n → 3n + 1）&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>これをずーっと繰り返していくと、&lt;strong>どんな数字も最終的には1に到達する&lt;/strong> っていう予想なんですね。&lt;/p>
&lt;p>たとえば、&lt;code>6&lt;/code> から始めると：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">6 → 3 → 10 → 5 → 16 → 8 → 4 → 2 → 1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>ちゃんと「1」になりました。おかえりなさい！&lt;/p>
&lt;hr>
&lt;h2 id="コードでやってみようpythonでコラッツ">コードでやってみよう：Pythonでコラッツ
&lt;/h2>&lt;p>さて、こういうときはコードで試すのが早い！
Pythonで「コラッツ数列」を出力してみましょう。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">collatz&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">steps&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">n&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">//&lt;/span> &lt;span class="mi">2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">n&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">3&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">steps&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">steps&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 例：19から始めてみる&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">collatz&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">19&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>実行すると：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">[19, 58, 29, 88, 44, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>みごとに1に到達します。
けっこう寄り道してるのに、最後はしっかりゴールイン！&lt;/p>
&lt;p>ちなみに 29 から始めても、同じように1に到達します。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">pythonprint(collatz(29))
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>実行すると&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">[27, 82, 41, 124, 62, 31, 94, 47, 142, 71, 214, 107, 322, 161, 484, 242,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">121, 364, 182, 91, 274, 137, 412, 206, 103, 310, 155, 466, 233, 700, 350,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">175, 526, 263, 790, 395, 1186, 593, 1780, 890, 445, 1336, 668, 334, 167,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">502, 251, 754, 377, 1132, 566, 283, 850, 425, 1276, 638, 319, 958, 479,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1438, 719, 2158, 1079, 3238, 1619, 4858, 2429, 7288, 3644, 1822, 911,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">2734, 1367, 4102, 2051, 6154, 3077, 9232, 4616, 2308, 1154, 577, 1732,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">866, 433, 1300, 650, 325, 976, 488, 244, 122, 61, 184, 92, 46, 23, 70, 35,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>なんと、111ステップもかかります！&lt;/p>
&lt;p>しかも、途中で9000以上まで膨れ上がる場面も。
めちゃくちゃ寄り道してからゴールインするパターンですね。&lt;/p>
&lt;hr>
&lt;h2 id="で結局なにがすごいの">で、結局なにがすごいの？
&lt;/h2>&lt;p>この予想の何がすごいかというと、&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>証明されていないのに、どんな数でやっても1になるっぽい&lt;/strong>&lt;/p>
&lt;/blockquote>
&lt;p>ってところです。&lt;/p>
&lt;p>え？じゃあ、1兆とか、1京（けい）とかは…？&lt;/p>
&lt;p>と思った方、鋭い。
実際に計算機を使って「2の68乗」くらいまでは確かめられてて、
&lt;strong>すべて1に到達&lt;/strong> しています。信じられない…。&lt;/p>
&lt;p>でも、&lt;strong>「全部そうなる」と理論的に証明されたわけではない&lt;/strong> んです。
これが数学の世界でいう「未解決問題」。&lt;/p>
&lt;hr>
&lt;h2 id="コラッツさんって誰">コラッツさんって誰？
&lt;/h2>&lt;p>で、ここまで読んで「そもそもコラッツって誰？」って思いますよね。
ちゃんと紹介します！&lt;/p>
&lt;ul>
&lt;li>名前：&lt;strong>ローズ・コラッツ（Lothar Collatz）&lt;/strong>&lt;/li>
&lt;li>国籍：ドイツ&lt;/li>
&lt;li>生年：1910年〜1990年&lt;/li>
&lt;li>肩書き：数学者（関数解析や数論の分野で活躍）&lt;/li>
&lt;/ul>
&lt;p>1937年にこの予想を提案して、
その後、80年以上にわたって &lt;strong>誰も証明も反証もできていません&lt;/strong>。&lt;/p>
&lt;p>ちなみに、この問題はあまりにシンプルなのに奥が深すぎて、
あのポール・エルデシュ（超有名数学者）すらこう言ったとか。&lt;/p>
&lt;blockquote>
&lt;p>「数学はまだコラッツを扱うには未熟だ」&lt;/p>
&lt;/blockquote>
&lt;p>つまり、人類の数学がこの謎にまだ追いついていない説…。&lt;/p>
&lt;hr>
&lt;h2 id="難しい数式は必要ない">「難しい数式」は必要ない
&lt;/h2>&lt;p>コラッツ予想のいいところは、&lt;strong>誰でも遊べる&lt;/strong> ことです。&lt;/p>
&lt;p>紙とペンがあればできます。
Pythonでコードを書けば、自動で試せます。
それでいて、&lt;strong>最先端の数学者たちが本気で挑んでる&lt;/strong>。&lt;/p>
&lt;p>なんか、ワクワクしません？&lt;/p>
&lt;hr>
&lt;h2 id="おまけ一気に試すコード">おまけ：一気に試すコード
&lt;/h2>&lt;p>いろんな数字をまとめて試すコードも載せておきますね。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">21&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">steps&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">collatz&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">steps&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">（ステップ数: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">steps&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">）&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>これは「1～20」のコラッツ数列を一気に出してくれます。&lt;/p>
&lt;hr>
&lt;h2 id="結論この世界やっぱり不思議だ">結論：この世界、やっぱり不思議だ
&lt;/h2>&lt;p>というわけで、コラッツ予想。&lt;/p>
&lt;ul>
&lt;li>めちゃシンプルなのに&lt;/li>
&lt;li>誰も証明できなくて&lt;/li>
&lt;li>数学界では大問題&lt;/li>
&lt;/ul>
&lt;p>っていう、不思議のかたまりみたいな存在でした。&lt;/p>
&lt;p>プログラミング初心者でも試せるので、ぜひ遊んでみてください〜！&lt;/p>
&lt;hr>
&lt;h2 id="おすすめリンク興味ある人向け">おすすめリンク（興味ある人向け）
&lt;/h2>&lt;ul>
&lt;li>&lt;a class="link" href="https://ja.wikipedia.org/wiki/%e3%82%b3%e3%83%a9%e3%83%83%e3%83%84%e4%ba%88%e6%83%b3" target="_blank" rel="noopener"
>Wikipedia: コラッツ予想&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://arxiv.org/abs/1909.03562" target="_blank" rel="noopener"
>Terence Tao 論文（英文）&lt;/a>&lt;/li>
&lt;li>Pythonのビジュアライズ版作ってみるのも楽しいですよ！（要望があれば作ります）&lt;/li>
&lt;/ul>
&lt;hr>
&lt;p>もっとこういう「不思議系数学×プログラミング」ネタが知りたい人は、
お気軽に「もっと教えて」とリクエストしてみてください。
そのうち、リーマン予想とか素数の話とか、いろいろ紹介しますね！&lt;/p>
&lt;hr>
&lt;p>📮おわり！&lt;/p>
&lt;hr></description></item><item><title>ケルクホフスの原理</title><link>http://kenji.blog/p/%E3%82%B1%E3%83%AB%E3%82%AF%E3%83%9B%E3%83%95%E3%82%B9%E3%81%AE%E5%8E%9F%E7%90%86/</link><pubDate>Wed, 16 Apr 2025 23:53:08 +0900</pubDate><guid>http://kenji.blog/p/%E3%82%B1%E3%83%AB%E3%82%AF%E3%83%9B%E3%83%95%E3%82%B9%E3%81%AE%E5%8E%9F%E7%90%86/</guid><description>&lt;img src="http://kenji.blog/p/%E3%82%B1%E3%83%AB%E3%82%AF%E3%83%9B%E3%83%95%E3%82%B9%E3%81%AE%E5%8E%9F%E7%90%86/img_2.png" alt="Featured image of post ケルクホフスの原理" />&lt;h1 id="ケルクホフスの原理">ケルクホフスの原理
&lt;/h1>&lt;hr>
&lt;p>こんにちは！&lt;/p>
&lt;p>今日はちょっと面白くて、実はものすごく大事な「ケルクホフスの原理」というお話をしてみたいと思います。&lt;/p>
&lt;p>あ、待って待って。&lt;br>
「ケルクホフスの原理」って聞いたことないし、カタカナ多くてすでにちょっとアレ…って思った方もいるかもしれません。安心してください。この記事は、そんな方にこそ読んでほしい内容なんです。&lt;/p>
&lt;hr>
&lt;h2 id="安全な暗号ってどういうこと">「安全な暗号」って、どういうこと？
&lt;/h2>&lt;p>たとえば誰かが「この金庫、秘密の開け方を知ってる人しか開けられません」って言ってきたとします。&lt;/p>
&lt;p>それって一見、めっちゃ安心に見えますよね。&lt;br>
でも、よく考えてみるとちょっと不安じゃないですか？&lt;/p>
&lt;p>「その秘密、バレたら終わりでは？」みたいな。&lt;/p>
&lt;p>実は、これがケルクホフスの原理が登場するきっかけなんです。&lt;/p>
&lt;hr>
&lt;h2 id="そもそもケルクホフスの原理ってなに">そもそも「ケルクホフスの原理」ってなに？
&lt;/h2>&lt;p>これ、ものすごくざっくり言うと、&lt;/p>
&lt;p>&lt;strong>「暗号は、仕組みがバレても安全であるべきだ」&lt;/strong> という考え方です。&lt;/p>
&lt;p>もっと言えば、「安全性は“秘密の鍵”だけに頼るべきで、暗号の方法そのものは公開されててもOK！」ということです。&lt;/p>
&lt;p>逆に言えば、「暗号のアルゴリズム（仕組み）を秘密にしてるだけの状態は、信頼性が低い」と見なされちゃうんです。&lt;/p>
&lt;hr>
&lt;h2 id="仕組みが秘密なら安心はちょっと危険かもしれません">「仕組みが秘密なら安心」は、ちょっと危険かもしれません
&lt;/h2>&lt;p>よくあるのが、こんな考え方。&lt;/p>
&lt;blockquote>
&lt;p>「このアプリの中身は誰にも見せてないから、セキュリティは大丈夫」&lt;/p>
&lt;/blockquote>
&lt;p>気持ちは分かります。&lt;br>
でも、それって「誰も見てないから悪いところも見つからないし、大丈夫だよね」って言ってるのと同じです。&lt;/p>
&lt;p>実際には、その“誰も見てない”こと自体がリスクになっちゃうこともあるんです。&lt;/p>
&lt;hr>
&lt;h2 id="でもなんでそんな原理が大事なの">でも、なんでそんな原理が大事なの？
&lt;/h2>&lt;p>というのも、もし誰かが仕組みを手に入れて、簡単に解読できちゃったら、その暗号はアウトです。&lt;/p>
&lt;p>例えるなら、ドアの鍵がめっちゃ複雑な仕組みでできてるんだけど、実は100円ショップで作れる合鍵で開いちゃう、みたいな感じです。&lt;/p>
&lt;p>「鍵が秘密だから大丈夫」じゃなくて、「仕組みを全部見せても、ちゃんとした鍵がないと開けられない」が大事なんですね。&lt;/p>
&lt;hr>
&lt;h2 id="でもなんか怖くないという気持ち">「でも、なんか怖くない？」という気持ち
&lt;/h2>&lt;p>ここで多くの人が感じるのが、&lt;/p>
&lt;blockquote>
&lt;p>「仕組みを全部さらけ出すって、なんか怖くない？」&lt;/p>
&lt;/blockquote>
&lt;p>という不安です。&lt;/p>
&lt;p>分かります。&lt;br>
だって「中身を全部見せたら、真似されたり、悪用されたりしないの？」って思っちゃいますよね。&lt;/p>
&lt;p>でも、そこがまさにケルクホフスの原理の肝なんです。&lt;br>
「中身を見せても崩れない強さ」こそが、ホンモノのセキュリティ、というわけです。&lt;/p>
&lt;hr>
&lt;h2 id="とはいえ最初はちょっと勇気がいります">とはいえ、最初はちょっと勇気がいります
&lt;/h2>&lt;p>開発者の気持ちになってみると、「仕組みを公開する＝弱点も見られる」ようで、そりゃあドキドキします。&lt;/p>
&lt;p>でも、考えてみてください。&lt;/p>
&lt;p>仕組みをちゃんと見せた上で「誰でも検証していいよ」と言えるものの方が、結果的に信頼されます。&lt;/p>
&lt;p>それって、人間関係と似てますよね。&lt;/p>
&lt;p>「本当の自分を見せた上で仲良くしてくれる人」って、やっぱり一番安心できます。&lt;/p>
&lt;hr>
&lt;h2 id="というわけで">というわけで
&lt;/h2>&lt;p>ケルクホフスの原理って、ちょっと理屈っぽく聞こえるかもしれませんが、本質はとてもシンプルです。&lt;/p>
&lt;p>&lt;strong>「誰に見せても壊れない仕組みを作ろう」&lt;/strong> というだけの話なんですね。&lt;/p>
&lt;p>表面的な秘密よりも、ちゃんとした設計。&lt;br>
誰にも見せたくないコードより、見せても恥ずかしくないコード。&lt;/p>
&lt;p>そういう「強さ」が、これからの時代にはますます求められていくのかもしれません。&lt;/p>
&lt;hr>
&lt;p>読んでくれてありがとうございました！&lt;/p>
&lt;p>セキュリティの話ってちょっと難しいけど、でも「人との関係」とか「日常の安心感」にもつながる部分があるんですよね。&lt;br>
気負わず、でもちょっとずつ知っていくと、きっといいことあると思います。&lt;/p>
&lt;hr>
&lt;p>&lt;img src="http://kenji.blog/p/%E3%82%B1%E3%83%AB%E3%82%AF%E3%83%9B%E3%83%95%E3%82%B9%E3%81%AE%E5%8E%9F%E7%90%86/img.png"
width="189"
height="282"
srcset="http://kenji.blog/p/%E3%82%B1%E3%83%AB%E3%82%AF%E3%83%9B%E3%83%95%E3%82%B9%E3%81%AE%E5%8E%9F%E7%90%86/img_hu715032b7fe5224f655ebb7d29b676305_77325_480x0_resize_box_3.png 480w, http://kenji.blog/p/%E3%82%B1%E3%83%AB%E3%82%AF%E3%83%9B%E3%83%95%E3%82%B9%E3%81%AE%E5%8E%9F%E7%90%86/img_hu715032b7fe5224f655ebb7d29b676305_77325_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="Auguste Kerckhoffs"
class="gallery-image"
data-flex-grow="67"
data-flex-basis="160px"
>&lt;/p></description></item><item><title>P≠NP予想</title><link>http://kenji.blog/p/pnp%E4%BA%88%E6%83%B3/</link><pubDate>Wed, 11 Sep 2024 02:22:39 +0900</pubDate><guid>http://kenji.blog/p/pnp%E4%BA%88%E6%83%B3/</guid><description>&lt;h1 id="概要">概要
&lt;/h1>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">クラスPとは、決定性チューリングマシンにおいて、多項式時間で判定可能な問題のクラスであり、クラスNPは、Yesとなる証拠（Witnessという）が与えられたとき、多項式時間でWitnessの正当性の判定（これを検証という）が可能な問題のクラスである。多項式時間で判定可能な問題は、多項式時間で検証可能であるので、P⊆NPであることは明らかであるが、PがNPの真部分集合であるか否かについては明確ではない。証明はまだないが、多くの研究者はP≠NPだと信じている。そして、このクラスPとクラスNPが等しくないという予想を「P≠NP予想」という。
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>参考サイト : &lt;a class="link" href="https://daigakudenki.com/np-hard/" target="_blank" rel="noopener"
>https://daigakudenki.com/np-hard/&lt;/a>&lt;/p></description></item><item><title>アインシュタインの名言</title><link>http://kenji.blog/p/%E3%82%A2%E3%82%A4%E3%83%B3%E3%82%B7%E3%83%A5%E3%82%BF%E3%82%A4%E3%83%B3%E3%81%AE%E5%90%8D%E8%A8%80/</link><pubDate>Sat, 24 Aug 2024 18:38:47 +0900</pubDate><guid>http://kenji.blog/p/%E3%82%A2%E3%82%A4%E3%83%B3%E3%82%B7%E3%83%A5%E3%82%BF%E3%82%A4%E3%83%B3%E3%81%AE%E5%90%8D%E8%A8%80/</guid><description>&lt;img src="http://kenji.blog/p/%E3%82%A2%E3%82%A4%E3%83%B3%E3%82%B7%E3%83%A5%E3%82%BF%E3%82%A4%E3%83%B3%E3%81%AE%E5%90%8D%E8%A8%80/Solvay_conference_1927.jpg" alt="Featured image of post アインシュタインの名言" />&lt;p>こんにちは！&lt;/p>
&lt;p>今日は、アインシュタインの名言についてお話ししたいと思います。&lt;/p>
&lt;hr>
&lt;h2 id="世界はあなたの善行を評価しない">世界はあなたの善行を評価しない？
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">世界はあなたが行う百万回の善を評価することは決してありません。
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">しかし、あなたが行う一つの間違ったことを批判するでしょう...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">しかし、落胆しないでください
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">「常にすべての笑いと批判を超えて立ち上がってください。強くあり続けろ。」
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- アルベルト・アインシュタイン
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>これは、アインシュタインが語ったとされる言葉です。私たちが日々感じる社会の厳しさや、人々の評価の偏りを鋭く指摘しています。&lt;/p>
&lt;hr>
&lt;h2 id="それでも立ち上がり続ける">それでも、立ち上がり続ける
&lt;/h2>&lt;p>「常にすべての笑いと批判を超えて立ち上がってください。強くあり続けろ。」&lt;/p>
&lt;p>この続きの言葉は、前述の厳しい現実に対するアインシュタインの答えとも言えるでしょう。批判や嘲笑に屈せず、自分自身を信じて前進し続けることの大切さを教えてくれます。&lt;/p>
&lt;hr>
&lt;h2 id="日常に活かすアインシュタインの教え">日常に活かすアインシュタインの教え
&lt;/h2>&lt;p>この名言は、私たちの日常生活にも深く関わっています。例えば、職場での努力が認められず、些細なミスだけが目立ってしまうことがあります。また、SNSでの発言が一部だけ切り取られて批判されることもあるでしょう。&lt;/p>
&lt;p>そんな時、このアインシュタインの言葉を思い出してみてください。他人の評価に一喜一憂するのではなく、自分の信念を持ち続けることが大切です。&lt;/p>
&lt;hr>
&lt;h2 id="まとめ">まとめ
&lt;/h2>&lt;p>アインシュタインのこの名言は、私たちに「他人の評価に左右されず、自分自身を信じて生きる」ことの重要性を教えてくれます。批判や嘲笑に負けず、自分の信じる道を進む勇気を持ちましょう。&lt;/p>
&lt;p>最後に、アインシュタインの言葉をもう一度。&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>「常にすべての笑いと批判を超えて立ち上がってください。強くあり続けろ。」&lt;/strong>&lt;/p>
&lt;/blockquote>
&lt;p>この言葉が、あなたの心に響き、前向きな一歩を踏み出すきっかけとなれば幸いです。&lt;/p></description></item><item><title>素数を生成するC言語コード</title><link>http://kenji.blog/p/%E7%B4%A0%E6%95%B0%E3%82%92%E7%94%9F%E6%88%90%E3%81%99%E3%82%8Bc%E8%A8%80%E8%AA%9E%E3%82%B3%E3%83%BC%E3%83%89/</link><pubDate>Sat, 24 Aug 2024 09:38:10 +0900</pubDate><guid>http://kenji.blog/p/%E7%B4%A0%E6%95%B0%E3%82%92%E7%94%9F%E6%88%90%E3%81%99%E3%82%8Bc%E8%A8%80%E8%AA%9E%E3%82%B3%E3%83%BC%E3%83%89/</guid><description>&lt;img src="http://kenji.blog/p/%E7%B4%A0%E6%95%B0%E3%82%92%E7%94%9F%E6%88%90%E3%81%99%E3%82%8Bc%E8%A8%80%E8%AA%9E%E3%82%B3%E3%83%BC%E3%83%89/img.png" alt="Featured image of post 素数を生成するC言語コード" />&lt;p>以下は、指定された範囲内の素数を生成するシンプルなC言語のコードです。この例では、1からnまでの素数を列挙します。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;stdio.h&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;stdbool.h&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">bool&lt;/span> &lt;span class="nf">isPrime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">num&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">num&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="nb">false&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">num&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="nb">true&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">num&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="o">||&lt;/span> &lt;span class="n">num&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="mi">3&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="nb">false&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">num&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="mi">6&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">num&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="o">||&lt;/span> &lt;span class="n">num&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">i&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="nb">false&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">true&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">void&lt;/span> &lt;span class="nf">printPrimes&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">printf&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;2 &amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">isPrime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">printf&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;%d &amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">printf&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">int&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">printf&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;素数を生成する範囲の最大値を入力してください: &amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">scanf&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;%d&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">printf&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;1から%dまでの素数は以下の通りです:&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">printPrimes&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>このコードは以下のように動作します：&lt;/p>
&lt;ol>
&lt;li>isPrime関数: 与えられた数が素数かどうかを判定します。効率を考慮して、2と3で割り切れるかどうかを最初にチェックし、その後6の倍数でチェックを進めます。&lt;/li>
&lt;li>printPrimes関数: 指定された範囲内の素数を出力します。2は最初に出力し、その後奇数だけをチェックします。&lt;/li>
&lt;li>main関数: ユーザーから範囲の最大値を入力してもらい、その範囲内の素数を出力します。&lt;/li>
&lt;/ol>
&lt;p>このコードをコンパイルして実行すると、指定された範囲内の素数が表示されます。&lt;/p></description></item><item><title>Mathematica入門</title><link>http://kenji.blog/p/mathematica%E5%85%A5%E9%96%80/</link><pubDate>Thu, 25 Jul 2024 01:36:19 +0900</pubDate><guid>http://kenji.blog/p/mathematica%E5%85%A5%E9%96%80/</guid><description>&lt;img src="http://kenji.blog/p/mathematica%E5%85%A5%E9%96%80/img.png" alt="Featured image of post Mathematica入門" />&lt;h1 id="mathematica入門">Mathematica入門
&lt;/h1>&lt;h2 id="方程式を解く">方程式を解く
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Solve[x^2 - 3 x + 2 == 0, x]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">{{x -&amp;gt; 1}, {x -&amp;gt; 2}}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="整数の範囲で方程式の解を求める">整数の範囲で方程式の解を求める
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Solve[x^2 - 3 x + 2 == 0 &amp;amp;&amp;amp; 0 &amp;lt;= x &amp;lt;= 2, x, Integers]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">{{x -&amp;gt; 1}, {x -&amp;gt; 2}}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="連立方程式を解く">連立方程式を解く
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Solve[{x + y == 3, x - y == 1}, {x, y}]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">{{x -&amp;gt; 2, y -&amp;gt; 1}}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="不等式を解く">不等式を解く
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Reduce[x^2 - 3 x + 2 &amp;gt; 0, x]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">x &amp;lt; 1 || x &amp;gt; 2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="微分する">微分する
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">D[x^2, x]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">2 x
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="積分する">積分する
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Integrate[x^2, x]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">x^3/3
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="極限を求める">極限を求める
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Limit[1/x, x -&amp;gt; 0]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Infinity
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="級数を求める">級数を求める
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Sum[1/n^2, {n, 1, Infinity}]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">π^2/6
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="行列を作成する">行列を作成する
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">m = {{1, 2}, {3, 4}}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="行列の積を求める">行列の積を求める
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">m . m
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">{{7, 10}, {15, 22}}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="逆行列を求める">逆行列を求める
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Inverse[m]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">{{-2, 1}, {1.5, -0.5}}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="固有値と固有ベクトルを求める">固有値と固有ベクトルを求める
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Eigensystem[m]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">{{5, 0}, {{1, 1}, {1, -1}}}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="ベクトルの内積を求める">ベクトルの内積を求める
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">{1, 2} . {3, 4}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">11
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="ベクトルの外積を求める">ベクトルの外積を求める
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Cross[{1, 2, 3}, {4, 5, 6}]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">{-3, 6, -3}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="ベクトルの大きさを求める">ベクトルの大きさを求める
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Norm[{1, 2, 3}]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">√14
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="ベクトルの角度を求める">ベクトルの角度を求める
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">ArcCos[{1, 2} . {3, 4}/(Norm[{1, 2}] Norm[{3, 4}])]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">ArcCos[11/(√5 √25)]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="ベクトルの射影を求める">ベクトルの射影を求める
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">{1, 2} . {3, 4}/Norm[{3, 4}] {3, 4}/Norm[{3, 4}]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">{11/5, 22/5}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="ベクトルの回転を求める">ベクトルの回転を求める
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">RotationMatrix[π/2].{1, 0}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">{0, 1}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="ベクトルの平行移動を求める">ベクトルの平行移動を求める
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">TranslationTransform[{1, 2}][{3, 4}]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">{4, 6}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="ベクトルの拡大縮小を求める">ベクトルの拡大縮小を求める
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">ScalingTransform[{2, 3}][{1, 1}]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">{2, 3}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="ベクトルの反転を求める">ベクトルの反転を求める
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">ReflectionTransform[{1, 1}][{1, 1}]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">{0, 0}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="乱数を生成する">乱数を生成する
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">RandomReal[]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">0.123456
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="乱数を生成する整数">乱数を生成する（整数）
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">RandomInteger[]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">123456
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="乱数を生成する範囲指定">乱数を生成する（範囲指定）
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">RandomReal[{1, 10}]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">5.6789
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="乱数を生成する整数範囲指定">乱数を生成する（整数、範囲指定）
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">RandomInteger[{1, 10}]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">5
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="乱数を生成する分布指定">乱数を生成する（分布指定）
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">RandomVariate[NormalDistribution[0, 1]]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">0.123456
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="乱数を生成する分布指定個数指定">乱数を生成する（分布指定、個数指定）
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">RandomVariate[NormalDistribution[0, 1], 10]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">{0.123456, 0.234567, ..., 0.987654}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="乱数を生成する分布指定個数指定シード指定">乱数を生成する（分布指定、個数指定、シード指定）
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">SeedRandom[12345]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">RandomVariate[NormalDistribution[0, 1], 10]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">{0.123456, 0.234567, ..., 0.987654}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="配列の要素に関数を適用する">配列の要素に関数を適用する
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Map[Sqrt, {1, 4, 9}]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Sqrt /@ {1, 4, 9}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Map[#^(1/2)&amp;amp;, {1, 4, 9}]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">{1, 2, 3}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="ラムダ式を使って関数を定義する">ラムダ式を使って関数を定義する
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">f = Function[x, x^2]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">f[3]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">9
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="関数を合成する">関数を合成する
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">f = Function[x, x^2]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">g = Function[x, x + 1]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">h = Function[x, f[g[x]]]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">h[3]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">16
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="直前の計算結果を参照する">直前の計算結果を参照する
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">% + 1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">17
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="純関数">純関数
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">(#+3)&amp;amp;[5]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">8
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="配列の抽出">配列の抽出
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Select[{1, 2, 3, 4, 5}, EvenQ]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Select[{1, 2, 3, 4, 5}, Mod[#,2]==0&amp;amp;]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">{2, 4}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>バースデイパラドックスとは</title><link>http://kenji.blog/p/%E3%83%90%E3%83%BC%E3%82%B9%E3%83%87%E3%82%A4%E3%83%91%E3%83%A9%E3%83%89%E3%83%83%E3%82%AF%E3%82%B9%E3%81%A8%E3%81%AF/</link><pubDate>Tue, 02 Apr 2024 01:20:50 +0900</pubDate><guid>http://kenji.blog/p/%E3%83%90%E3%83%BC%E3%82%B9%E3%83%87%E3%82%A4%E3%83%91%E3%83%A9%E3%83%89%E3%83%83%E3%82%AF%E3%82%B9%E3%81%A8%E3%81%AF/</guid><description>&lt;img src="http://kenji.blog/p/%E3%83%90%E3%83%BC%E3%82%B9%E3%83%87%E3%82%A4%E3%83%91%E3%83%A9%E3%83%89%E3%83%83%E3%82%AF%E3%82%B9%E3%81%A8%E3%81%AF/img.png" alt="Featured image of post バースデイパラドックスとは" />&lt;h2 id="バースデイパラドックスって知ってる">バースデイパラドックスって知ってる？
&lt;/h2>&lt;p>ちょっと不思議な話をします。
「同じ誕生日の人がいる確率」って、何人くらい集まれば高くなると思いますか？&lt;/p>
&lt;p>たとえば、1年は365日あるので、「23人集まって、誰かと誕生日がかぶる確率は50%以上」って言われると…なんだか直感に反する感じがしますよね。&lt;/p>
&lt;p>でもこれ、&lt;strong>本当に50%以上なんです。&lt;/strong>&lt;/p>
&lt;hr>
&lt;h2 id="なぜそんなことが起きるのか">なぜそんなことが起きるのか？
&lt;/h2>&lt;p>この現象は「バースデイパラドックス」と呼ばれています。
名前は「パラドックス（逆説）」ですが、ちゃんとした数学的な理由があります。&lt;/p>
&lt;p>人数を「n」としたとき、&lt;strong>誰も誕生日がかぶらない確率&lt;/strong> は次の式で求められます：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">P(誰もかぶらない) = 365/365 × 364/365 × 363/365 × ... × (365 - n + 1)/365
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>それを1から引くことで、「誰かとかぶる確率」が出てきます。&lt;/p>
&lt;hr>
&lt;h2 id="結果を見てみると">結果を見てみると…
&lt;/h2>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>人数&lt;/th>
&lt;th>同じ誕生日の人がいる確率&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>10人&lt;/td>
&lt;td>約11.7%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>20人&lt;/td>
&lt;td>約41.1%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>23人&lt;/td>
&lt;td>&lt;strong>約50.7%（ここが注目！）&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>30人&lt;/td>
&lt;td>約70.6%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>70人&lt;/td>
&lt;td>&lt;strong>なんと約99.9%！&lt;/strong>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>つまり、たった &lt;strong>23人&lt;/strong> いれば、半分以上の確率で誰かと誕生日がかぶるんです。
学校のクラスや職場の会議でも、けっこう当てはまりそうですよね。&lt;/p>
&lt;hr>
&lt;h2 id="まとめ直感と数学のズレが面白い">まとめ：直感と数学のズレが面白い
&lt;/h2>&lt;p>「バースデイパラドックス」は、私たちの直感と、実際の数学的な確率がズレる面白い例です。
こういう話を知っておくと、ちょっとした雑談やクイズで盛り上がれるかもしれません！&lt;/p>
&lt;hr>
&lt;h2 id="参考リンク">参考リンク
&lt;/h2>&lt;ul>
&lt;li>&lt;a class="link" href="https://ja.wikipedia.org/wiki/%E8%AA%95%E7%94%9F%E6%97%A5%E3%81%AE%E3%83%91%E3%83%A9%E3%83%89%E3%83%83%E3%82%AF%E3%82%B9" target="_blank" rel="noopener"
>誕生日のパラドックス（Wikipedia）&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>モンティ・ホール問題</title><link>http://kenji.blog/p/%E3%83%A2%E3%83%B3%E3%83%86%E3%82%A3%E3%83%9B%E3%83%BC%E3%83%AB%E5%95%8F%E9%A1%8C/</link><pubDate>Sun, 31 Mar 2024 23:41:51 +0900</pubDate><guid>http://kenji.blog/p/%E3%83%A2%E3%83%B3%E3%83%86%E3%82%A3%E3%83%9B%E3%83%BC%E3%83%AB%E5%95%8F%E9%A1%8C/</guid><description>&lt;img src="http://kenji.blog/p/%E3%83%A2%E3%83%B3%E3%83%86%E3%82%A3%E3%83%9B%E3%83%BC%E3%83%AB%E5%95%8F%E9%A1%8C/img_1.png" alt="Featured image of post モンティ・ホール問題" />&lt;h2 id="モンティホール問題とは">モンティ・ホール問題とは
&lt;/h2>&lt;p>モンティ・ホール問題とは、アメリカのテレビ番組「Let&amp;rsquo;s Make a Deal」で行われていたゲームの一つで、以下のような問題です。&lt;/p>
&lt;p>前提条件：3つのドアのうち1つに賞品が入っており、残りの2つにはハズレが入っている。&lt;/p>
&lt;ol>
&lt;li>参加者は3つのドアのうち1つを選びます。&lt;/li>
&lt;li>司会者は、参加者が選んだドア以外の2つのドアのうち、ハズレの1つのドアを開けます。&lt;/li>
&lt;li>参加者には、選んだドアを変更するかどうかを尋ねます。&lt;/li>
&lt;/ol>
&lt;p>このとき、参加者はドアを変更するほうがよいか、変更しないほうがよいかを考える問題です。&lt;/p>
&lt;h2 id="解法">解法
&lt;/h2>&lt;p>モンティ・ホール問題の解法は、以下のようになります。&lt;/p>
&lt;ol>
&lt;li>
&lt;p>参加者が最初に選んだドアを変更しない場合&lt;/p>
&lt;ul>
&lt;li>当たりの確率：1/3&lt;/li>
&lt;li>外れの確率：2/3&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>司会者がハズレのドアを開けた後&lt;/p>
&lt;ul>
&lt;li>変更しない場合、当たりの確率：1/3 (1.の当たりの確率から変わらない)&lt;/li>
&lt;li>変更する場合、当たりの確率：2/3 (1.の当たり以外の確率)&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>したがって、参加者がドアを変更するほうが当たりの確率が高くなります。&lt;/p>
&lt;h2 id="参考">参考
&lt;/h2>&lt;ul>
&lt;li>Wikipedia &lt;a class="link" href="https://en.wikipedia.org/wiki/Monty_Hall_problem" target="_blank" rel="noopener"
>Monty Hall problem&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>数学の未解決問題</title><link>http://kenji.blog/p/%E6%95%B0%E5%AD%A6%E3%81%AE%E6%9C%AA%E8%A7%A3%E6%B1%BA%E5%95%8F%E9%A1%8C/</link><pubDate>Sat, 02 Mar 2024 22:57:36 +0900</pubDate><guid>http://kenji.blog/p/%E6%95%B0%E5%AD%A6%E3%81%AE%E6%9C%AA%E8%A7%A3%E6%B1%BA%E5%95%8F%E9%A1%8C/</guid><description>&lt;img src="http://kenji.blog/p/%E6%95%B0%E5%AD%A6%E3%81%AE%E6%9C%AA%E8%A7%A3%E6%B1%BA%E5%95%8F%E9%A1%8C/img.png" alt="Featured image of post 数学の未解決問題" />&lt;h1 id="数学の未解決問題">数学の未解決問題
&lt;/h1>&lt;p>数学の未解決問題について説明します。問題自体はシンプルでも、証明されていない問題がまだまだたくさんあります。&lt;/p>
&lt;h2 id="完全数は無数にあるか">完全数は無数にあるか？
&lt;/h2>&lt;p>完全数とは、自分自身を除く正の約数の和が自分自身に等しい自然数です。
例えば、&lt;/p>
&lt;ul>
&lt;li>6は約数は1,2,3となり、1+2+3=6なので完全数です。&lt;/li>
&lt;li>28は約数は1,2,4,7,14となり、1+2+4+7+14=28なので完全数です。&lt;/li>
&lt;/ul>
&lt;p>現在51個しか発見されていませんが、無数にあると予想されていまが、
まだ、証明されていません。&lt;/p>
&lt;h2 id="ゴールドバッハの予想">ゴールドバッハの予想
&lt;/h2>&lt;p>ゴールドバッハの予想は、すべての2よりも大きな偶数は2つの素数の和として表すことができるという予想です。
（ここで素数とは、1と自分自身以外の約数を持たない自然数です。）&lt;/p>
&lt;p>例えば、&lt;/p>
&lt;ul>
&lt;li>4=2+2&lt;/li>
&lt;li>6=3+3&lt;/li>
&lt;li>8=3+5&lt;/li>
&lt;li>10=3+7=5+5&lt;/li>
&lt;/ul>
&lt;p>問題自体は非常にシンプルですが、未だに証明されていません。&lt;/p>
&lt;h2 id="リーマン予想">リーマン予想
&lt;/h2>&lt;p>リーマンゼータ関数の零点が、負の偶数と、実部が 1 / 2 の複素数に限られるという予想である。&lt;/p>
&lt;p>リーマンゼータ関数は、$s$を複素数、$n$を自然数とするとき、&lt;/p>
$$\zeta(s):=\sum _{n=1}^{\infty }{\frac {1}{n^{s}}}=1+{\frac {1}{2^{s}}}+{\frac {1}{3^{s}}}+{\frac {1}{4^{s}}}+\cdots$$
&lt;p>で定義される関数$\zeta$のことをいう。&lt;/p></description></item><item><title>数学の歴史</title><link>http://kenji.blog/p/%E6%95%B0%E5%AD%A6%E3%81%AE%E6%AD%B4%E5%8F%B2/</link><pubDate>Sat, 22 Jul 2023 15:25:10 +0900</pubDate><guid>http://kenji.blog/p/%E6%95%B0%E5%AD%A6%E3%81%AE%E6%AD%B4%E5%8F%B2/</guid><description>&lt;img src="http://kenji.blog/p/%E6%95%B0%E5%AD%A6%E3%81%AE%E6%AD%B4%E5%8F%B2/img.png" alt="Featured image of post 数学の歴史" />&lt;h3 id="古代ギリシアの三大作図問題">古代ギリシアの三大作図問題
&lt;/h3>&lt;ol>
&lt;li>円が与えられたとき、その円と同じ面積をもつ正方形を作る（円の方形化問題）&lt;/li>
&lt;li>任意の角が指定されたとき、それを三等分する（角の三等分問題）&lt;/li>
&lt;li>立方体が与えられたとき、その二倍の体積をもつ立方体を作る（立方体の倍積問題）&lt;/li>
&lt;/ol>
&lt;h3 id="アルキメデスの螺旋">アルキメデスの螺旋
&lt;/h3>&lt;p>平面上で、半直線OBを定点Oの周りに一様な速さで回転させます。初めの位置をOAとすると、
OAから動き始めると同時に点PがOから出発し、OBに沿って一定の速さで動くとき、点Pが描く
線がアルキメデスの螺旋です。&lt;/p>
&lt;h3 id="パップスの定理">パップスの定理
&lt;/h3>&lt;ul>
&lt;li>サイクロイド&lt;/li>
&lt;li>ニコメデスのコンコイド&lt;/li>
&lt;li>ディオクレスのシソイド&lt;/li>
&lt;li>フェルマの接線法&lt;/li>
&lt;li>デカルトの法線法&lt;/li>
&lt;/ul>
&lt;h3 id="年表">年表
&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>年&lt;/th>
&lt;th>出来事&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>紀元前3400頃&lt;/td>
&lt;td>シュメール人が粘土製の代用硬貨で勘定を行う&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>紀元前3000年頃&lt;/td>
&lt;td>エジプトでヒエログリフの数学が登場&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>紀元前2800年頃&lt;/td>
&lt;td>インダス文明で１０進法に則った度量衡が使われる&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>紀元前2700年頃&lt;/td>
&lt;td>エジプト人がロープとピタゴラス数を使って角度を確認&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>紀元前2500年頃&lt;/td>
&lt;td>計算に使う道具、アバカスが発見される&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>紀元前2500年頃&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="参考">参考
&lt;/h3>&lt;ul>
&lt;li>&lt;a class="link" href="https://ja.wikipedia.org/wiki/%E6%95%B0%E5%AD%A6%E3%81%AE%E6%AD%B4%E5%8F%B2" target="_blank" rel="noopener"
>数学の歴史&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>エラトステネスの篩を使って1000以下の素数を列挙する方法</title><link>http://kenji.blog/p/%E3%82%A8%E3%83%A9%E3%83%88%E3%82%B9%E3%83%86%E3%83%8D%E3%82%B9%E3%81%AE%E7%AF%A9%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A61000%E4%BB%A5%E4%B8%8B%E3%81%AE%E7%B4%A0%E6%95%B0%E3%82%92%E5%88%97%E6%8C%99%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/</link><pubDate>Sun, 09 Apr 2023 12:54:24 +0900</pubDate><guid>http://kenji.blog/p/%E3%82%A8%E3%83%A9%E3%83%88%E3%82%B9%E3%83%86%E3%83%8D%E3%82%B9%E3%81%AE%E7%AF%A9%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A61000%E4%BB%A5%E4%B8%8B%E3%81%AE%E7%B4%A0%E6%95%B0%E3%82%92%E5%88%97%E6%8C%99%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/</guid><description>&lt;img src="http://kenji.blog/p/%E3%82%A8%E3%83%A9%E3%83%88%E3%82%B9%E3%83%86%E3%83%8D%E3%82%B9%E3%81%AE%E7%AF%A9%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A61000%E4%BB%A5%E4%B8%8B%E3%81%AE%E7%B4%A0%E6%95%B0%E3%82%92%E5%88%97%E6%8C%99%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/img.png" alt="Featured image of post エラトステネスの篩を使って1000以下の素数を列挙する方法" />&lt;h2 id="エラトステネスの篩とは">エラトステネスの篩とは
&lt;/h2>&lt;p>エラトステネスの篩とは、ある数以下の素数を列挙するアルゴリズムです。
アルゴリズムは単純で、以下の手順で実装できます。&lt;/p>
&lt;ol>
&lt;li>Nの要素をもつbool値配列を作成し、全要素をtrueで初期化する&lt;/li>
&lt;li>配列の0番目と1番目の要素をfalseにする(0と1は素数ではないため)&lt;/li>
&lt;li>配列の2番目の要素がtrueなら、2を素数として出力する&lt;/li>
&lt;li>配列の$2^2$以上の2の倍数番目の要素をすべてfalseにする※&lt;/li>
&lt;li>配列の3番目の要素がtrueなら、3を素数として出力する&lt;/li>
&lt;li>配列の$3^2$以上の3の倍数番目の要素をすべてfalseにする&lt;/li>
&lt;li>4番目、5番目、・・・、N番目の要素について、同様の処理を繰り返す&lt;/li>
&lt;/ol>
&lt;p>※2乗以上の要素をfalseの対象としているのは、2乗より小さい数についてはすでに処理済み(列挙が完了している)であるためです。&lt;/p>
&lt;p>&lt;img src="http://kenji.blog/p/%E3%82%A8%E3%83%A9%E3%83%88%E3%82%B9%E3%83%86%E3%83%8D%E3%82%B9%E3%81%AE%E7%AF%A9%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A61000%E4%BB%A5%E4%B8%8B%E3%81%AE%E7%B4%A0%E6%95%B0%E3%82%92%E5%88%97%E6%8C%99%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/Animation_Sieb_des_Eratosthenes.gif"
width="445"
height="369"
srcset="http://kenji.blog/p/%E3%82%A8%E3%83%A9%E3%83%88%E3%82%B9%E3%83%86%E3%83%8D%E3%82%B9%E3%81%AE%E7%AF%A9%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A61000%E4%BB%A5%E4%B8%8B%E3%81%AE%E7%B4%A0%E6%95%B0%E3%82%92%E5%88%97%E6%8C%99%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/Animation_Sieb_des_Eratosthenes_hua63c6218ac9f9cdba93ccb20db392e0e_206214_480x0_resize_box_1.gif 480w, http://kenji.blog/p/%E3%82%A8%E3%83%A9%E3%83%88%E3%82%B9%E3%83%86%E3%83%8D%E3%82%B9%E3%81%AE%E7%AF%A9%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A61000%E4%BB%A5%E4%B8%8B%E3%81%AE%E7%B4%A0%E6%95%B0%E3%82%92%E5%88%97%E6%8C%99%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/Animation_Sieb_des_Eratosthenes_hua63c6218ac9f9cdba93ccb20db392e0e_206214_1024x0_resize_box_1.gif 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="120"
data-flex-basis="289px"
>&lt;/p>
&lt;h2 id="rustでの実装">Rustでの実装
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">fn main() {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> let n = 1000;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> let mut is_prime = vec![true; n+1];
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> is_prime[0] = false;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> is_prime[1] = false;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> for i in 2..=n {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> if is_prime[i] {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> println!(&amp;#34;{}&amp;#34;, i);
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> let mut j = i * i;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> while j &amp;lt;= n {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> is_prime[j] = false;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> j += i;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> }
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> }
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> }
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="少し高速化版">少し高速化版
&lt;/h2>&lt;p>下記の点を考慮して、少し高速化した実装を行います。&lt;/p>
&lt;ul>
&lt;li>配列の初期化をtrueで初期化するのではなく、falseで初期化する（このほうが高速）&lt;/li>
&lt;li>2の倍数は素数ではないので、2の倍数の要素をfalseにする処理を省略&lt;/li>
&lt;li>nまでループする必要はなく、nの平方根までの素数を列挙すれば、n以下の素数を列挙できる&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">fn main() {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> let n = 1000;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> let mut is_prime = vec![false; n+1];
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> is_prime[2] = true;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> for i in (3..=n).step_by(2) {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> is_prime[i] = true;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> }
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> for i in 3..=((n as f64).sqrt() as usize) {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> if is_prime[i] {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> let mut j = i * i;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> while j &amp;lt;= n {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> is_prime[j] = false;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> j += i * 2;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> }
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> }
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> }
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> for i in (2..=n).filter(|&amp;amp;x| is_prime[x]) {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> println!(&amp;#34;{}&amp;#34;, i);
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> }
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="参考">参考
&lt;/h2>&lt;ul>
&lt;li>&lt;a class="link" href="https://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%A9%E3%83%88%E3%82%B9%E3%83%86%E3%83%8D%E3%82%B9%E3%81%AE%E7%AF%A9" target="_blank" rel="noopener"
>エラトステネスの篩&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Python(matplotlib.pyplot)を使ってグラフを描画する方法</title><link>http://kenji.blog/p/pythonmatplotlib.pyplot%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%82%B0%E3%83%A9%E3%83%95%E3%82%92%E6%8F%8F%E7%94%BB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/</link><pubDate>Sun, 09 Apr 2023 01:02:19 +0900</pubDate><guid>http://kenji.blog/p/pythonmatplotlib.pyplot%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%82%B0%E3%83%A9%E3%83%95%E3%82%92%E6%8F%8F%E7%94%BB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/</guid><description>&lt;img src="http://kenji.blog/p/pythonmatplotlib.pyplot%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%82%B0%E3%83%A9%E3%83%95%E3%82%92%E6%8F%8F%E7%94%BB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/img.png" alt="Featured image of post Python(matplotlib.pyplot)を使ってグラフを描画する方法" />&lt;p>&lt;img src="http://kenji.blog/p/pythonmatplotlib.pyplot%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%82%B0%E3%83%A9%E3%83%95%E3%82%92%E6%8F%8F%E7%94%BB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/img_1.png"
width="1200"
height="288"
srcset="http://kenji.blog/p/pythonmatplotlib.pyplot%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%82%B0%E3%83%A9%E3%83%95%E3%82%92%E6%8F%8F%E7%94%BB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/img_1_hue3f23818eeeec9c43d6452cc0f61fb52_43864_480x0_resize_box_3.png 480w, http://kenji.blog/p/pythonmatplotlib.pyplot%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%82%B0%E3%83%A9%E3%83%95%E3%82%92%E6%8F%8F%E7%94%BB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/img_1_hue3f23818eeeec9c43d6452cc0f61fb52_43864_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="img_1.png"
class="gallery-image"
data-flex-grow="416"
data-flex-basis="1000px"
>&lt;/p>
&lt;h1 id="必要なもの">必要なもの
&lt;/h1>&lt;ul>
&lt;li>Google アカウント&lt;/li>
&lt;/ul>
&lt;h1 id="手順">手順
&lt;/h1>&lt;ol>
&lt;li>&lt;a class="link" href="https://colab.research.google.com/" target="_blank" rel="noopener"
>https://colab.research.google.com/&lt;/a> にアクセス&lt;/li>
&lt;li>「ファイル」→「ノートブックを新規作成」を選択&lt;/li>
&lt;li>下記のコードを貼り付けて実行&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">matplotlib.pyplot&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">plt&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">numpy&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">np&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">linspace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pi&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">500&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">plt&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">plot&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sin&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">label&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sin curve&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">plt&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">plot&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">cos&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">label&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;cos curve&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">plt&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">legend&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="c1"># 凡例の表示&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">plt&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">show&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h1 id="実行結果">実行結果
&lt;/h1>&lt;p>&lt;img src="http://kenji.blog/p/pythonmatplotlib.pyplot%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%82%B0%E3%83%A9%E3%83%95%E3%82%92%E6%8F%8F%E7%94%BB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/img.png"
width="568"
height="413"
srcset="http://kenji.blog/p/pythonmatplotlib.pyplot%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%82%B0%E3%83%A9%E3%83%95%E3%82%92%E6%8F%8F%E7%94%BB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/img_hucdb24ab588d845f9f7a56ef99be2c709_27745_480x0_resize_box_3.png 480w, http://kenji.blog/p/pythonmatplotlib.pyplot%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%82%B0%E3%83%A9%E3%83%95%E3%82%92%E6%8F%8F%E7%94%BB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/img_hucdb24ab588d845f9f7a56ef99be2c709_27745_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="img.png"
class="gallery-image"
data-flex-grow="137"
data-flex-basis="330px"
>&lt;/p>
&lt;h1 id="参考">参考
&lt;/h1>&lt;ul>
&lt;li>&lt;a class="link" href="https://matplotlib.org/3.5.3/api/_as_gen/matplotlib.pyplot.html" target="_blank" rel="noopener"
>matplotlib.pyplot — Matplotlib 3.5.3 documentation&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>hugoでKaTeX(LaTeX風数式表示)を有効にする方法</title><link>http://kenji.blog/p/hugo%E3%81%A7katexlatex%E9%A2%A8%E6%95%B0%E5%BC%8F%E8%A1%A8%E7%A4%BA%E3%82%92%E6%9C%89%E5%8A%B9%E3%81%AB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/</link><pubDate>Fri, 31 Mar 2023 23:11:26 +0900</pubDate><guid>http://kenji.blog/p/hugo%E3%81%A7katexlatex%E9%A2%A8%E6%95%B0%E5%BC%8F%E8%A1%A8%E7%A4%BA%E3%82%92%E6%9C%89%E5%8A%B9%E3%81%AB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/</guid><description>&lt;img src="http://kenji.blog/p/hugo%E3%81%A7katexlatex%E9%A2%A8%E6%95%B0%E5%BC%8F%E8%A1%A8%E7%A4%BA%E3%82%92%E6%9C%89%E5%8A%B9%E3%81%AB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/img.png" alt="Featured image of post hugoでKaTeX(LaTeX風数式表示)を有効にする方法" />&lt;h1 id="katexとは">KaTeXとは
&lt;/h1>&lt;p>KaTeXは、LaTeX風の数式をHTMLで表示するためのjavascriptライブラリです。&lt;/p>
&lt;p>具体的には下記のような数式を表示することができます。&lt;/p>
$$f(x) = x^2 + x + 41$$
&lt;p>他にもLaTeX風な数式表示ライブラリもあるようですが、KaTeXはシンプルで高速と定評があるようです。&lt;/p>
&lt;h1 id="hugoへの導入方法">hugoへの導入方法
&lt;/h1>&lt;ol>
&lt;li>hugoのフォルダ階層で&lt;code>layouts/partials/math.html&lt;/code>を新規作成します。&lt;/li>
&lt;/ol>
&lt;p>中身は下記の通りにしてください。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">&amp;lt;link rel=&amp;#34;stylesheet&amp;#34; href=&amp;#34;https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.css&amp;#34; integrity=&amp;#34;sha384-vKruj+a13U8yHIkAyGgK1J3ArTLzrFGBbBc0tDp4ad/EyewESeXE/Iv67Aj8gKZ0&amp;#34; crossorigin=&amp;#34;anonymous&amp;#34;&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;lt;script defer src=&amp;#34;https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.js&amp;#34; integrity=&amp;#34;sha384-PwRUT/YqbnEjkZO0zZxNqcxACrXe+j766U2amXcgMg5457rve2Y7I6ZJSm2A0mS4&amp;#34; crossorigin=&amp;#34;anonymous&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;lt;script defer src=&amp;#34;https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/contrib/auto-render.min.js&amp;#34; integrity=&amp;#34;sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05&amp;#34; crossorigin=&amp;#34;anonymous&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;lt;script&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">document.addEventListener(&amp;#34;DOMContentLoaded&amp;#34;, function() {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> renderMathInElement(
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> document.body,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> delimiters: [
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> {left: &amp;#34;$$&amp;#34;, right: &amp;#34;$$&amp;#34;, display: true},
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> {left: &amp;#34;\\[&amp;#34;, right: &amp;#34;\\]&amp;#34;, display: true},
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> {left: &amp;#34;$&amp;#34;, right: &amp;#34;$&amp;#34;, display: false},
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> {left: &amp;#34;\\(&amp;#34;, right: &amp;#34;\\)&amp;#34;, display: false}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> });
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> });
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;lt;/script&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="2">
&lt;li>次に既存のファイル&lt;code>layouts/partials/extend_head.html&lt;/code>に下記のコードを追加します。&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">{{ if or .Params.math .Site.Params.math }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ partial &amp;#34;math.html&amp;#34; . }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ end }}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="3">
&lt;li>これでKaTeXを使う準備が整いました。&lt;/li>
&lt;/ol>
&lt;p>ページのfront matterに&lt;code>math: true&lt;/code>を追加することで、KaTeXを有効にすることができます。&lt;/p>
&lt;ol start="4">
&lt;li>あとはページ記事の本文に、数式をLaTeX風に書くだけです。&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">$$ e^{i \pi} = -1 $$
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>上記のように記述すると、下記のように表示されます。&lt;/p>
$$ e^{i \pi} = -1 $$
&lt;h1 id="参考">参考
&lt;/h1>&lt;ul>
&lt;li>&lt;a class="link" href="https://reorx.github.io/hugo-PaperModX/docs/math-typesetting/" target="_blank" rel="noopener"
>Math Typesetting | PaperModX&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://katex.org/docs/autorender.html" target="_blank" rel="noopener"
>KaTex Auto-render Extension&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://www.storange.jp/2017/02/katex.html" target="_blank" rel="noopener"
>KaTeXの導入 | The Strange Storage&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Mathematicaで巡回セールスマン問題を解く</title><link>http://kenji.blog/p/mathematica%E3%81%A7%E5%B7%A1%E5%9B%9E%E3%82%BB%E3%83%BC%E3%83%AB%E3%82%B9%E3%83%9E%E3%83%B3%E5%95%8F%E9%A1%8C%E3%82%92%E8%A7%A3%E3%81%8F/</link><pubDate>Wed, 12 Oct 2022 19:05:58 +0900</pubDate><guid>http://kenji.blog/p/mathematica%E3%81%A7%E5%B7%A1%E5%9B%9E%E3%82%BB%E3%83%BC%E3%83%AB%E3%82%B9%E3%83%9E%E3%83%B3%E5%95%8F%E9%A1%8C%E3%82%92%E8%A7%A3%E3%81%8F/</guid><description>&lt;img src="http://kenji.blog/p/mathematica%E3%81%A7%E5%B7%A1%E5%9B%9E%E3%82%BB%E3%83%BC%E3%83%AB%E3%82%B9%E3%83%9E%E3%83%B3%E5%95%8F%E9%A1%8C%E3%82%92%E8%A7%A3%E3%81%8F/img.png" alt="Featured image of post Mathematicaで巡回セールスマン問題を解く" />&lt;h1 id="mathematicaで巡回セールスマン問題を解く">Mathematicaで巡回セールスマン問題を解く
&lt;/h1>&lt;h2 id="問題">問題
&lt;/h2>&lt;blockquote class="twitter-tweet">&lt;p lang="ja" dir="ltr">電車でこんな広告を見かけました😁📸 &lt;a href="https://t.co/iXEgvtXrpL">pic.twitter.com/iXEgvtXrpL&lt;/a>&lt;/p>&amp;mdash; 早稲田大学 早水桃子研究室 (@hayamizu_lab) &lt;a href="https://x.com/hayamizu_lab/status/1579806418982825984?ref_src=twsrc%5Etfw">October 11, 2022&lt;/a>&lt;/blockquote>
&lt;script async src="https://platform.x.com/widgets.js" charset="utf-8">&lt;/script>
&lt;h2 id="解法">解法
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">d=SparseArray[{{1,2}-&amp;gt;10,{2,1}-&amp;gt;10,{1,5}-&amp;gt;15,{5,1}-&amp;gt;15,{1,4}-&amp;gt;12,{4,1}-&amp;gt;12,{1,3}-&amp;gt;20,{3,1}-&amp;gt;20,{2,5}-&amp;gt;10,{5,2}-&amp;gt;10,{3,4}-&amp;gt;10,{4,3}-&amp;gt;10,{3,8}-&amp;gt;30,{8,3}-&amp;gt;30,{3,7}-&amp;gt;20,{7,3}-&amp;gt;20,{3,6}-&amp;gt;25,{6,3}-&amp;gt;25,{4,5}-&amp;gt;15,{5,4}-&amp;gt;15,{4,8}-&amp;gt;20,{8,4}-&amp;gt;20,{5,9}-&amp;gt;18,{9,5}-&amp;gt;18,{5,8}-&amp;gt;15,{8,5}-&amp;gt;15,{6,7}-&amp;gt;5,{7,6}-&amp;gt;5,{7,8}-&amp;gt;35,{8,7}-&amp;gt;35,{8,9}-&amp;gt;12,{9,8}-&amp;gt;12},{9,9},Infinity];
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>SparseArray関数で行列を作成する。それぞれの要素は、その要素の行と列の都市間の距離を表します。例えば、最初の要素&lt;code>{1,2}-&amp;gt;10&lt;/code>は、1と2の距離が10という意味です。最後から2番目の要素&lt;code>{9,9}&lt;/code>は行列の大きさを示していて、最後の要素&lt;code>Infinity&lt;/code>は、指定していない都市間の道の長さが無限。つまり道がないことを意味します。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">{len,tour}=FindShortestTour[{1,2,3,4,5,6,7,8,9},DistanceFunction-&amp;gt;(d[[#1,#2]]&amp;amp;)]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>FindShortestTour関数で、簡単に巡回セールスマン問題を解くことができます。&lt;code>{1,2,3,4,5,6,7,8,9}&lt;/code>は、都市の番号を表します。&lt;code>DistanceFunction-&amp;gt;(d[[#1,#2]]&amp;amp;)&lt;/code>は、都市間の距離を表す行列dを渡しています。&lt;/p>
&lt;h2 id="出力">出力
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">{137, {1, 2, 5, 9, 8, 7, 6, 3, 4}}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力は、最短距離と、そのときの巡回路です。最短距離は&lt;code>137&lt;/code>、巡回路は&lt;code>1→2→5→9→8→7→6→3→4→1&lt;/code>となります。ABCの順に直すと&lt;code>A, B, E, I, H, G, F, C, D&lt;/code>となります。&lt;/p></description></item><item><title>好きな数式</title><link>http://kenji.blog/p/%E5%A5%BD%E3%81%8D%E3%81%AA%E6%95%B0%E5%BC%8F/</link><pubDate>Wed, 05 Oct 2022 13:24:50 +0900</pubDate><guid>http://kenji.blog/p/%E5%A5%BD%E3%81%8D%E3%81%AA%E6%95%B0%E5%BC%8F/</guid><description>&lt;img src="http://kenji.blog/p/%E5%A5%BD%E3%81%8D%E3%81%AA%E6%95%B0%E5%BC%8F/img.png" alt="Featured image of post 好きな数式" />&lt;h2 id="ウィルソンの定理">ウィルソンの定理
&lt;/h2>&lt;p>$p$ を素数とするとき，$(p−1)!≡−1 \pmod p$ が成り立つ&lt;/p>
&lt;h2 id="オイラーの公式">オイラーの公式
&lt;/h2>&lt;p>$e^{iπ}+1=0$&lt;/p>
&lt;h2 id="フェルマーの最終定理">フェルマーの最終定理
&lt;/h2>&lt;p>$n≥3$ なる整数 $n$ に対して，$x^n+y^n=z^n$ を満たす正の整数の組 $x,y,z$ は存在しない&lt;/p>
&lt;h2 id="バーゼル問題">バーゼル問題
&lt;/h2>&lt;p>$1/1^2+1/2^2+1/3^2+1/4^2+...=π^2/6$&lt;/p>
&lt;h2 id="オイラーの素数生成式">オイラーの素数生成式
&lt;/h2>&lt;p>$n^2+n+41$ は $n$ が $0$ 以上 $39$ 以下の整数のとき，全て素数となる&lt;/p></description></item><item><title>なぜ数学や計算機が好きなんだろう</title><link>http://kenji.blog/p/%E3%81%AA%E3%81%9C%E6%95%B0%E5%AD%A6%E3%82%84%E8%A8%88%E7%AE%97%E6%A9%9F%E3%81%8C%E5%A5%BD%E3%81%8D%E3%81%AA%E3%82%93%E3%81%A0%E3%82%8D%E3%81%86/</link><pubDate>Fri, 23 Sep 2022 01:56:52 +0900</pubDate><guid>http://kenji.blog/p/%E3%81%AA%E3%81%9C%E6%95%B0%E5%AD%A6%E3%82%84%E8%A8%88%E7%AE%97%E6%A9%9F%E3%81%8C%E5%A5%BD%E3%81%8D%E3%81%AA%E3%82%93%E3%81%A0%E3%82%8D%E3%81%86/</guid><description>&lt;img src="http://kenji.blog/p/%E3%81%AA%E3%81%9C%E6%95%B0%E5%AD%A6%E3%82%84%E8%A8%88%E7%AE%97%E6%A9%9F%E3%81%8C%E5%A5%BD%E3%81%8D%E3%81%AA%E3%82%93%E3%81%A0%E3%82%8D%E3%81%86/img.png" alt="Featured image of post なぜ数学や計算機が好きなんだろう" />&lt;h2 id="なぜ数学や計算機が好きなんだろうか考えてみました">なぜ数学や計算機が好きなんだろうか考えてみました
&lt;/h2>&lt;h3 id="すべての人に平等">すべての人に平等
&lt;/h3>&lt;p>人や立場、場所を選ばず同じインプットに対していつも同じアウトプットを返す。&lt;/p>
&lt;h3 id="ルールが明確">ルールが明確
&lt;/h3>&lt;p>ルールが明確に定まっていて、不条理や不正義がないこと。&lt;/p>
&lt;h3 id="導き出した答えや理論は永遠に正しい">導き出した答えや理論は永遠に正しい
&lt;/h3>&lt;p>一度はじき出した答えが後から書き換えられる心配がない。&lt;/p>
&lt;h3 id="程よい難しさがある">程よい難しさがある
&lt;/h3>&lt;p>常に未解決の問題があり、いつでも課題解決に挑戦できる。&lt;/p></description></item><item><title>数学の偉人たち</title><link>http://kenji.blog/p/%E6%95%B0%E5%AD%A6%E3%81%AE%E5%81%89%E4%BA%BA%E3%81%9F%E3%81%A1/</link><pubDate>Thu, 22 Sep 2022 23:06:37 +0900</pubDate><guid>http://kenji.blog/p/%E6%95%B0%E5%AD%A6%E3%81%AE%E5%81%89%E4%BA%BA%E3%81%9F%E3%81%A1/</guid><description>&lt;img src="http://kenji.blog/p/%E6%95%B0%E5%AD%A6%E3%81%AE%E5%81%89%E4%BA%BA%E3%81%9F%E3%81%A1/img.png" alt="Featured image of post 数学の偉人たち" />&lt;h3 id="フェルマー-p-de-fermat-1601-1665">フェルマー (P, de Fermat, 1601-1665)
&lt;/h3>&lt;p>17世紀を代表するフランスの数学者。解析幾何、確率論、微分法などの基礎付を行った。また数論の始祖でもある。&lt;/p>
&lt;h3 id="ディオファントス-diophantus-207頃-291頃">ディオファントス (Diophantus, 207頃-291頃)
&lt;/h3>&lt;p>ギリシアの数学者。記号法の導入、有理数解の研究で有名。著書『算術』が代表作。方程式の有理数解を求める分野をディオファントス解析と呼ぶ。&lt;/p>
&lt;h3 id="オイラー-l-euler-1707-1783">オイラー (L. Euler, 1707-1783)
&lt;/h3>&lt;p>スイスの生んだ数学王。ありとあらゆる数学において業績を挙げた。論文700以上、著書45編が残されている。&lt;/p>
&lt;h3 id="ルジャンドル-a-m-legendre-1752-1833">ルジャンドル (A. M. Legendre, 1752-1833)
&lt;/h3>&lt;p>フランスの数学者。整数論、楕円積分、引力問題などで多数の業績を残した。「数論」という言葉は彼の主著『数論』に由来する。&lt;/p>
&lt;h3 id="クンマー-e-e-kummer-1810-1893">クンマー (E. E. Kummer, 1810-1893)
&lt;/h3>&lt;p>ドイツの数学者。円分体の整数論をフェルマーの大定理に応用して大きな成果を挙げた。&lt;/p>
&lt;h3 id="デカルト-r-descartes-1596-1650">デカルト (R. Descartes, 1596-1650)
&lt;/h3>&lt;p>フランスの独創的な哲学者。代表的著作として『方法序説』、『幾何学』、『宇宙論』など。&lt;/p>
&lt;h3 id="パスカル-b-pascal-1623-1662">パスカル (B. Pascal, 1623-1662)
&lt;/h3>&lt;p>確率論や流体の研究で知られるフランスの哲学者。後にヤンセン派に所属し、宗教活動に従事した。『パンセ』はそのときの著作である。&lt;/p>
&lt;h3 id="バシェ-c-g-bachet-1581-1638">バシェ (C. G. Bachet, 1581-1638)
&lt;/h3>&lt;p>フランスの貴族で、趣味として数のパズルの研究を行った。ディオファントスの『算術』のラテン訳を刊行し、これに自分の研究を注釈として掲載した。&lt;/p>
&lt;h3 id="ウォリス-j-wallis-1616-1703">ウォリス (J. Wallis, 1616-1703)
&lt;/h3>&lt;p>イギリスの数学者。主著『無限の算術』で極限の概念に数学的な形式を与え、微積分学の基礎作りに貢献した。&lt;/p>
&lt;h3 id="ブランカー-w-brouncker-1620-1684">ブランカー (W. Brouncker, 1620-1684)
&lt;/h3>&lt;p>アイルランドの貴族。王立協会（英国学士院）の初代会長。数学愛好家で、ウォリスなどと交流があった。&lt;/p>
&lt;h3 id="ラグランジュ-j-l-lagrange-1736-1813">ラグランジュ (J. L. Lagrange, 1736-1813)
&lt;/h3>&lt;p>イタリア生まれのフランスの数学者。オイラーの後任としてベルリン学士院数学部長を勤めた。整数論、解析力学などで大きな業績を挙げた。&lt;/p>
&lt;h3 id="ジーゲル-c-l-siegel-1896-1981">ジーゲル (C. L. Siegel, 1896-1981)
&lt;/h3>&lt;p>ドイツの数論学者。数の解析的理論において数々の貢献をなした。&lt;/p>
&lt;h3 id="フィボナッチ-l-fibonacci-1175頃-1250頃">フィボナッチ (L. Fibonacci, 1175頃-1250頃)
&lt;/h3>&lt;p>イタリアの数学者。主著『算盤の書』でインド・アラビア数字を用い、普及に務めた。また『平方の書』で合同数を論じた。&lt;/p>
&lt;h3 id="ベーカー-a-baker-1939-">ベーカー (A. Baker, 1939-)
&lt;/h3>&lt;p>イギリスの数論学者。超越数論における貢献で、広中平祐とともにフィールズ賞を授与された。&lt;/p>
&lt;h3 id="ポアンカレ-j-poincare-1854-1912">ポアンカレ (J. Poincare, 1854-1912)
&lt;/h3>&lt;p>最後の万能数学者と呼ばれたフランスの数学者。保型関数論、非ユークリッド幾何、微分方程式、天体力学、電気力学などをはじめ、科学的評論でも卓越した著作を残した。&lt;/p>
&lt;h3 id="モーデル-l-j-mordell-1888-1972">モーデル (L. J. Mordell, 1888-1972)
&lt;/h3>&lt;p>アメリカ生まれの数学者。両親はリトアニアからの移民。不定方程式論において数多くの論文があるが、楕円曲線論におけるモーデルの定理はとりわけ有名。ヴェイユがこれを一般の代数曲線の場合に拡張して、算術的代数幾何は、ここから爆発的な発展を遂げることになる。&lt;/p>
&lt;h3 id="ヴェイユ-a-weil-1906-">ヴェイユ (A. Weil, 1906-)
&lt;/h3>&lt;p>ユダヤ系のフランスの数学者。若い頃、フェルマー問題に関心を持ち、数論に応用する目的で代数幾何学を根本的に見直し、厳格な基礎付けを行った。数学史の著作でも知られている。&lt;/p>
&lt;h3 id="メルセンヌ-m-mersenne-1588-1648">メルセンヌ (M. Mersenne, 1588-1648)
&lt;/h3>&lt;p>フランスのミニム派の神父。各地の数学者の往復書簡を取り持った。メルセンヌ数という名の数も、実はフェルマーが考え出した数である。&lt;/p>
&lt;h3 id="ロベルヴァル-g-p-de-roberval-1602-1675">ロベルヴァル (G. P. de Roberval, 1602-1675)
&lt;/h3>&lt;p>フランスの数学者。当時、数学者として教授の職を得ていたほぼ唯一の人で、サイクロイドの研究などで知られる。&lt;/p>
&lt;h3 id="アーベル-n-h-abel-1802-1829">アーベル (N. H. Abel, 1802-1829)
&lt;/h3>&lt;p>ノルウェーの数学者。一般5次方程式の不可解性、楕円関数論、アーベル積分論などすぐれた業績を挙げたが、若くして没した。&lt;/p>
&lt;h3 id="ヤコビ-k-g-jacob-1804-1851">ヤコビ (K. G. Jacob, 1804-1851)
&lt;/h3>&lt;p>ユダヤ系ドイツの数学者。楕円関数論、データ関数論、微分方程式、変分学などにおいて大きな業績を残した。アーベルの業績を世に紹介した。科学の目的を「人間精神の名誉」のためとし、実用主義を排したことでも知られる。&lt;/p>
&lt;h3 id="ガウス-c-f-gauss-1777-1855">ガウス (C. F. Gauss, 1777-1855)
&lt;/h3>&lt;p>ドイツの生んだ数学王。整数論、非ユークリッド幾何、測地学、超幾何級数、曲面論、地磁気の研究などで知られる。完全主義者で、足場の見えぬほどまでに完成度が高くないと成果を公表しなかったとされる。主著『算術研究』など。&lt;/p>
&lt;h3 id="ラメ-g-lame-1795-1870">ラメ (G. Lame, 1795-1870)
&lt;/h3>&lt;p>フランスの数学者。弾性力学、熱伝導論などに貢献がある。&lt;/p>
&lt;h3 id="リューヴィル-j-liouville-1809-1882">リューヴィル (J. Liouville, 1809-1882)
&lt;/h3>&lt;p>フランスの数学者。微分方程式、超越整数論、関数論に貢献した。&lt;/p>
&lt;h3 id="コーシー-a-l-cauchy-1789-1857">コーシー (A. L. Cauchy, 1789-1857)
&lt;/h3>&lt;p>フランスの数学者。多産で理論物理、数学に業績が多い。フランスではガウスに匹敵するほど尊敬されているという。&lt;/p>
&lt;h3 id="ガロア-e-galois-1811-1832">ガロア (E. Galois, 1811-1832)
&lt;/h3>&lt;p>フランスの数学者。5次以上の方程式は一般には代数的に解けないというアーベルの定理を群という概念を導入して解明した。若くして決闘に倒れたが、つまらぬ女性問題がきっかけだったことが現在ではわかっている。&lt;/p>
&lt;h3 id="ヘンゼル-k-hensel-1861-1941">ヘンゼル (K, Hensel, 1861-1941)
&lt;/h3>&lt;p>ドイツの数学者。クロネッカーの弟子。関数論的手法を応用して数論に p 進法(p 進解析)という理論を導入した。&lt;/p>
&lt;h3 id="ハーセ-h-hesse-1898-1979">ハーセ (H. Hesse, 1898-1979)
&lt;/h3>&lt;p>ドイツの数学者。ヘンゼルの弟子で、p 進解析の基礎付けとその応用に貢献した。類体論の整備、楕円曲線の L 関数の研究など。&lt;/p>
&lt;h3 id="クロネッカー-l-kronecker-1823-1891">クロネッカー (L. Kronecker, 1823-1891)
&lt;/h3>&lt;p>ユダヤ系ドイツの数学者。楕円関数論、数論などに貢献。数学の算術的基礎付けを提唱したことでも知られるが、主観性の強い性格で、ベルリン大学の同僚のワイヤストラスに対して理不尽な批判をしたり、カントールの就職を妨げたりしたことは彼の生涯に負のイメージを与えている。&lt;/p>
&lt;h3 id="ヒルベルト-d-hilbert-1862-1943">ヒルベルト (D. Hilbert, 1862-1943)
&lt;/h3>&lt;p>ドイツの数学者。不変式論、代数的整数論、数学基礎論をはじめ、数学のあらゆル分野に巨大な足跡を残した。パリの国際数学者会議(1900)で提唱した23の問題は数学の発展に大きな影響を与えた。&lt;/p>
&lt;h3 id="リーマン-b-riemann-1826-1866">リーマン (B. Riemann, 1826-1866)
&lt;/h3>&lt;p>ドイツの数学者。複素関数論におけるリーマン面の概念、リーマン幾何学など、数学の根本に関わる大きな業績を挙げた。&lt;/p>
&lt;h3 id="ファルチングス-g-faltings-1954-">ファルチングス (G. Faltings, 1954-)
&lt;/h3>&lt;p>ドイツの数学者。1983年にモーデル予想を解決した。&lt;/p>
&lt;h3 id="ワイルズ-a-wiles-1953-">ワイルズ (A, Wiles, 1953-)
&lt;/h3>&lt;p>イギリス生まれの数学者。岩澤の主予想、バーチ=スウィンナトンダイア予想などの研究で大きな貢献をした、この分野の第一人者。&lt;/p>
&lt;h3 id="参考文献">参考文献
&lt;/h3>&lt;p>フェルマーの大定理が解けた！オイラーからワイルズの証明まで　講談社&lt;/p></description></item><item><title>数学者が登場する映画</title><link>http://kenji.blog/p/%E6%95%B0%E5%AD%A6%E8%80%85%E3%81%8C%E7%99%BB%E5%A0%B4%E3%81%99%E3%82%8B%E6%98%A0%E7%94%BB/</link><pubDate>Mon, 05 Sep 2022 10:41:00 +0900</pubDate><guid>http://kenji.blog/p/%E6%95%B0%E5%AD%A6%E8%80%85%E3%81%8C%E7%99%BB%E5%A0%B4%E3%81%99%E3%82%8B%E6%98%A0%E7%94%BB/</guid><description>&lt;img src="http://kenji.blog/p/%E6%95%B0%E5%AD%A6%E8%80%85%E3%81%8C%E7%99%BB%E5%A0%B4%E3%81%99%E3%82%8B%E6%98%A0%E7%94%BB/images/img.png" alt="Featured image of post 数学者が登場する映画" />&lt;p>数学者の主人公が登場する私のおすすめの映画3選です。&lt;/p>
&lt;h1 id="ビューティフルマインド">ビューティフル・マインド
&lt;/h1>&lt;p>&lt;img src="http://kenji.blog/images/beautiful_mind.jpg"
loading="lazy"
>&lt;br>
実在するアメリカの天才数学者の半生を描いた作品。最後は驚きの展開に。
主演のラッセルクロウがいい味出しています。&lt;/p>
&lt;h1 id="エニグマ">エニグマ
&lt;/h1>&lt;p>&lt;img src="http://kenji.blog/images/enigma.jpg"
loading="lazy"
>&lt;/p>
&lt;blockquote>
&lt;p>ロバート・ハリスの小説『暗号機エニグマへの挑戦』を映画化した2001年公開の映画。
wikipediaより&lt;/p>
&lt;/blockquote>
&lt;p>エニグマ暗号機というドイツがつく出した暗号を解読する物語。&lt;/p>
&lt;h1 id="イミテーションゲーム">イミテーション・ゲーム
&lt;/h1>&lt;p>&lt;img src="http://kenji.blog/images/imitation_game.jpg"
loading="lazy"
>&lt;/p>
&lt;p>こちらもエニグマを扱った暗号解読の物語。当時の世界観が好きです。&lt;/p>
&lt;h1 id="奇跡がくれた数式">奇跡がくれた数式
&lt;/h1>&lt;p>&lt;img src="http://kenji.blog/p/%E6%95%B0%E5%AD%A6%E8%80%85%E3%81%8C%E7%99%BB%E5%A0%B4%E3%81%99%E3%82%8B%E6%98%A0%E7%94%BB/img.png"
width="566"
height="800"
srcset="http://kenji.blog/p/%E6%95%B0%E5%AD%A6%E8%80%85%E3%81%8C%E7%99%BB%E5%A0%B4%E3%81%99%E3%82%8B%E6%98%A0%E7%94%BB/img_hu224d39544ca0af082720aacd7902fd19_1089949_480x0_resize_box_3.png 480w, http://kenji.blog/p/%E6%95%B0%E5%AD%A6%E8%80%85%E3%81%8C%E7%99%BB%E5%A0%B4%E3%81%99%E3%82%8B%E6%98%A0%E7%94%BB/img_hu224d39544ca0af082720aacd7902fd19_1089949_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="img.png"
class="gallery-image"
data-flex-grow="70"
data-flex-basis="169px"
>&lt;/p>
&lt;p>ケンブリッジ大学の数学者ハーディと、インドの数学者ラマヌジャンの交流を描いた作品。数学の美しさを感じることができます。&lt;/p>
&lt;h1 id="博士と彼女のセオリー">博士と彼女のセオリー
&lt;/h1>&lt;p>&lt;img src="http://kenji.blog/p/%E6%95%B0%E5%AD%A6%E8%80%85%E3%81%8C%E7%99%BB%E5%A0%B4%E3%81%99%E3%82%8B%E6%98%A0%E7%94%BB/img_1.png"
width="800"
height="459"
srcset="http://kenji.blog/p/%E6%95%B0%E5%AD%A6%E8%80%85%E3%81%8C%E7%99%BB%E5%A0%B4%E3%81%99%E3%82%8B%E6%98%A0%E7%94%BB/img_1_hubfe00de5360673c8281820134bf7a309_739706_480x0_resize_box_3.png 480w, http://kenji.blog/p/%E6%95%B0%E5%AD%A6%E8%80%85%E3%81%8C%E7%99%BB%E5%A0%B4%E3%81%99%E3%82%8B%E6%98%A0%E7%94%BB/img_1_hubfe00de5360673c8281820134bf7a309_739706_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="img_1.png"
class="gallery-image"
data-flex-grow="174"
data-flex-basis="418px"
>&lt;/p>
&lt;p>ホーキング博士の半生を描いた作品。&lt;/p>
&lt;h1 id="パーティクルフィーバー">パーティクル・フィーバー
&lt;/h1>&lt;p>&lt;img src="http://kenji.blog/p/%E6%95%B0%E5%AD%A6%E8%80%85%E3%81%8C%E7%99%BB%E5%A0%B4%E3%81%99%E3%82%8B%E6%98%A0%E7%94%BB/img_2.png"
width="640"
height="960"
srcset="http://kenji.blog/p/%E6%95%B0%E5%AD%A6%E8%80%85%E3%81%8C%E7%99%BB%E5%A0%B4%E3%81%99%E3%82%8B%E6%98%A0%E7%94%BB/img_2_hu18abd37eefb70a17a04950b9cdaa7d84_902746_480x0_resize_box_3.png 480w, http://kenji.blog/p/%E6%95%B0%E5%AD%A6%E8%80%85%E3%81%8C%E7%99%BB%E5%A0%B4%E3%81%99%E3%82%8B%E6%98%A0%E7%94%BB/img_2_hu18abd37eefb70a17a04950b9cdaa7d84_902746_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="img_2.png"
class="gallery-image"
data-flex-grow="66"
data-flex-basis="160px"
>&lt;/p></description></item><item><title>【数式で完全理解】古典最強「GNFS」はなぜ量子アルゴリズムに敗れるのか？素因数分解のパラダイムシフト</title><link>http://kenji.blog/p/gnfs-to-shors-algorithm-math-deepdive/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://kenji.blog/p/gnfs-to-shors-algorithm-math-deepdive/</guid><description>&lt;img src="http://kenji.blog/p/gnfs-to-shors-algorithm-math-deepdive/quantum_vs_gnfs_eyecatch_1788616101508.jpg" alt="Featured image of post 【数式で完全理解】古典最強「GNFS」はなぜ量子アルゴリズムに敗れるのか？素因数分解のパラダイムシフト" />&lt;p>現代のインターネット社会における情報セキュリティは、RSA暗号をはじめとする公開鍵暗号方式によって守られています。RSA暗号の安全性の根拠は、 &lt;strong>「巨大な合成数の素因数分解は計算量的に極めて困難である」&lt;/strong> という事実に依存しています。&lt;/p>
&lt;p>本記事では、古典コンピュータにおいて最強の素因数分解アルゴリズムである &lt;strong>「一般数体ふるい法」&lt;/strong> （General Number Field Sieve, GNFS）の数学的メカニズムを紐解くとともに、それがなぜピーター・ショアによって発見された &lt;strong>「Shorのアルゴリズム」&lt;/strong> によって完全に打ち破られるのか、そのパラダイムシフトを数式と概念図を用いて徹底的に深掘りします。&lt;/p>
&lt;hr>
&lt;h2 id="1-古典計算における素因数分解のアプローチフェルマーの素因数分解法からの発展">1. 古典計算における素因数分解のアプローチ：フェルマーの素因数分解法からの発展
&lt;/h2>&lt;p>素因数分解問題とは、与えられた合成数 $N$ に対して、$N = p \times q$ となる素数 $p, q$ を見つける問題です。&lt;/p>
&lt;p>基本的なアイデアは、次の合同式を満たす非自明な $x, y$ を見つけることに帰着します。&lt;/p>
$$ x^2 \equiv y^2 \pmod N $$
&lt;p>これを変形すると、&lt;/p>
$$ x^2 - y^2 \equiv 0 \pmod N $$
$$ (x - y)(x + y) \equiv 0 \pmod N $$
&lt;p>ここで、$x \not\equiv \pm y \pmod N$ であれば、$\gcd(x-y, N)$ または $\gcd(x+y, N)$ を計算することで、$N$ の非自明な因数を得ることができます。この事実がGNFSなどの近代的な素因数分解アルゴリズムの基礎となっています。&lt;/p>
&lt;hr>
&lt;h2 id="2-古典最強のアルゴリズム一般数体ふるい法gnfsの深淵">2. 古典最強のアルゴリズム：「一般数体ふるい法」（GNFS）の深淵
&lt;/h2>&lt;p>&lt;strong>「GNFS」&lt;/strong> は、今日知られている古典コンピュータ向けの素因数分解アルゴリズムの中で最も高速なものです。その時間計算量は、準指数関数的（Sub-exponential）な時間を要します。&lt;/p>
&lt;h3 id="gnfsの計算量">GNFSの計算量
&lt;/h3>&lt;p>数 $N$ の桁数を $b = \log_2 N$ としたとき、GNFSの計算量は次のように表されます。&lt;/p>
$$ O\left( \exp \left( \left(\frac{64}{9} b\right)^{1/3} (\log b)^{2/3} \right) \right) $$
&lt;p>この式からわかるように、計算量は多項式時間ではなく、指数関数よりはわずかに遅い &lt;strong>「準指数時間」&lt;/strong> となります。それでも桁数が増えれば計算時間は天文学的に増大します。&lt;/p>
&lt;h3 id="gnfsの数学的メカニズム">GNFSの数学的メカニズム
&lt;/h3>&lt;p>GNFSは大きく分けて4つのステップで構成されます。&lt;/p>
&lt;ol>
&lt;li>&lt;strong>多項式選択 (Polynomial Selection)&lt;/strong>&lt;/li>
&lt;li>&lt;strong>ふるい分け (Sieving)&lt;/strong>&lt;/li>
&lt;li>&lt;strong>行列の簡約化 (Matrix Reduction)&lt;/strong>&lt;/li>
&lt;li>&lt;strong>平方根の計算 (Square Root)&lt;/strong>&lt;/li>
&lt;/ol>
&lt;h4 id="21-多項式選択と代数体">2.1. 多項式選択と代数体
&lt;/h4>&lt;p>まず、整数を係数とする既約多項式 $f(x)$ と $g(x)$ を選びます。これらは共通の根 $m$ を modulo $N$ で持つように設定されます。すなわち、&lt;/p>
$$ f(m) \equiv 0 \pmod N $$
$$ g(m) \equiv 0 \pmod N $$
&lt;p>通常、$g(x)$ は一次多項式 $g(x) = x - m$ として選ばれます。$f(x)$ の根を $\alpha$ とおくと、$\mathbb{Q}(\alpha)$ という &lt;strong>「代数体」&lt;/strong> （Number Field）が構成されます。$\mathbb{Q}(\alpha)$ の環における演算と、通常の整数環 $\mathbb{Z}$ の演算を、準同型写像 $\phi: \alpha \mapsto m$ を通じて比較します。&lt;/p>
&lt;h4 id="22-ふるい分け-sieving">2.2. ふるい分け (Sieving)
&lt;/h4>&lt;p>次に、互いに素な整数のペア $(a, b)$ を大量に探索します。目的は、以下の2つの値がそれぞれ &lt;strong>「B-smooth」&lt;/strong> （比較的小さな素因数のみで構成される）になるようなペアを見つけることです。&lt;/p>
&lt;ol>
&lt;li>$a - bm$ （整数環上での値）&lt;/li>
&lt;li>$b^d f(a/b)$ （代数体上でのノルム $N(a - b\alpha)$ に対応）&lt;/li>
&lt;/ol>
&lt;p>ここで &lt;strong>「ふるい」&lt;/strong> （Sieve）と呼ばれる高速な探索手法が用いられます。これにより、膨大な候補の中から条件を満たす $(a, b)$ ペアを効率的に抽出します。&lt;/p>
&lt;h4 id="23-行列の簡約化-linear-algebra-over-gf2">2.3. 行列の簡約化 (Linear Algebra over GF(2))
&lt;/h4>&lt;p>集めたペア $(a, b)$ から、指数ベクトルを構成し、巨大な疎行列の左零空間を $\mathbb{F}_2$ （要素が0と1のみの体）上で求めます。&lt;/p>
&lt;p>関係式 $ \prod (a_i - b_i m) $ と $ \prod (a_i - b_i \alpha) $ がそれぞれ平方元になるように、ベクトル $v$ を解として見つけます。これは、&lt;/p>
$$ M \mathbf{x} \equiv \mathbf{0} \pmod 2 $$
&lt;p>という線形方程式系を解くことに他なりません。ここで、ブロック・ランチョス法（Block Lanczos Algorithm）やブロック・ウィーデマン法（Block Wiedemann Algorithm）などの高度な数値計算アルゴリズムが活用されます。&lt;/p>
&lt;h4 id="24-平方根の計算">2.4. 平方根の計算
&lt;/h4>&lt;p>最後に、代数体と整数環の双方で平方根を取り、$x^2 \equiv y^2 \pmod N$ という関係式を導き出します。そして、$\gcd(x-y, N)$ を計算し、因数を得ます。&lt;/p>
&lt;hr>
&lt;h2 id="3-量子計算によるブレイクスルーshorのアルゴリズム">3. 量子計算によるブレイクスルー：「Shorのアルゴリズム」
&lt;/h2>&lt;p>GNFSが準指数関数的な時間を必要とするのに対し、1994年にピーター・ショアが発表した &lt;strong>「Shorのアルゴリズム」&lt;/strong> は、量子コンピュータを用いることでこの問題を &lt;strong>「多項式時間」&lt;/strong> で解くことができます。&lt;/p>
&lt;h3 id="shorのアルゴリズムの計算量">Shorのアルゴリズムの計算量
&lt;/h3>&lt;p>量子ビット数を $O(\log N)$ としたとき、時間計算量は次のようになります。&lt;/p>
$$ O((\log N)^3) $$
&lt;p>これは、ビット数に対して指数関数的な爆発を起こさないことを意味します。 &lt;strong>「古典計算」&lt;/strong> の計算量が宇宙の寿命を超えるような巨大な合成数であっても、 &lt;strong>「量子計算」&lt;/strong> では数時間〜数日で解読可能になるという驚異的な結果です。&lt;/p>
&lt;h3 id="shorのアルゴリズムの全体像周期発見問題への帰着">Shorのアルゴリズムの全体像：周期発見問題への帰着
&lt;/h3>&lt;p>Shorのアルゴリズムは、素因数分解問題を &lt;strong>「周期発見問題」&lt;/strong> へと巧みに帰着させます。&lt;/p>
&lt;ol>
&lt;li>$N$ と互いに素なランダムな整数 $a$ を選ぶ（$1 &lt; a &lt; N$）。&lt;/li>
&lt;li>関数 $f(x) = a^x \bmod N$ を定義する。&lt;/li>
&lt;li>$f(x)$ の周期 $r$、すなわち $a^r \equiv 1 \pmod N$ となる最小の正整数 $r$ を見つける。&lt;/li>
&lt;li>$r$ が偶数であれば、$a^{r/2} \not\equiv -1 \pmod N$ かどうかを確認し、$\gcd(a^{r/2} \pm 1, N)$ を計算して素因数を得る。&lt;/li>
&lt;/ol>
&lt;p>このステップ3の &lt;strong>「周期 $r$ の発見」&lt;/strong> こそが、古典コンピュータでは指数関数的時間を要するボトルネックですが、量子コンピュータは &lt;strong>「量子重ね合わせ」&lt;/strong> と &lt;strong>「量子フーリエ変換」&lt;/strong> （QFT）を用いることで、これを一瞬で解決します。&lt;/p>
&lt;hr>
&lt;h2 id="4-量子フーリエ変換qftと周期の抽出">4. 量子フーリエ変換（QFT）と周期の抽出
&lt;/h2>&lt;p>Shorのアルゴリズムの核心である、量子状態の操作について数式で詳しく見ていきましょう。&lt;/p>
&lt;h3 id="41-量子重ね合わせの生成">4.1. 量子重ね合わせの生成
&lt;/h3>&lt;p>まず、2つの量子レジスタを用意します。レジスタ1は入力 $x$ の重ね合わせ状態を保持し、レジスタ2は関数の計算結果 $f(x)$ を保持します。初期状態 $|0\rangle |0\rangle$ に対してアダマール変換（Hadamard Transform）を適用し、すべての可能な $x$ の重ね合わせを作り出します。&lt;/p>
$$ |\psi_1\rangle = \frac{1}{\sqrt{Q}} \sum_{x=0}^{Q-1} |x\rangle |0\rangle $$
&lt;p>
（ここで $Q$ は $N^2 \le Q &lt; 2N^2$ を満たす2のべき乗）&lt;/p>
&lt;p>次に、量子オラクル $U_f$ を用いて $f(x) = a^x \bmod N$ を計算し、レジスタ2に格納します。&lt;/p>
$$ |\psi_2\rangle = U_f |\psi_1\rangle = \frac{1}{\sqrt{Q}} \sum_{x=0}^{Q-1} |x\rangle |a^x \bmod N\rangle $$
&lt;p>ここでレジスタ2を測定したと仮定しましょう（実際には測定しなくても数学的構造は同じです）。ある値 $y = a^{x_0} \bmod N$ が観測されたとすると、レジスタ1の状態は、$f(x) = y$ となるすべての $x$ の重ね合わせに収縮します。周期を $r$ とすると、そのような $x$ は $x_0, x_0 + r, x_0 + 2r, \dots$ となります。&lt;/p>
$$ |\psi_3\rangle = \frac{1}{\sqrt{M}} \sum_{k=0}^{M-1} |x_0 + kr\rangle $$
&lt;p>
（ここで $M \approx Q/r$ は項の数）&lt;/p>
&lt;p>この状態は、周期 $r$ の情報を内在していますが、直接測定してもランダムな $x_0 + kr$ が得られるだけで、周期 $r$ はわかりません。ここでQFTの出番です。&lt;/p>
&lt;h3 id="42-量子フーリエ変換-quantum-fourier-transform-の適用">4.2. 量子フーリエ変換 (Quantum Fourier Transform) の適用
&lt;/h3>&lt;p>QFTは、量子状態の振幅に対して離散フーリエ変換を行う操作です。状態 $|x\rangle$ に対するQFTの作用は以下のように定義されます。&lt;/p>
$$ \text{QFT} |x\rangle = \frac{1}{\sqrt{Q}} \sum_{y=0}^{Q-1} e^{2\pi i \frac{xy}{Q}} |y\rangle $$
&lt;p>これを $|\psi_3\rangle$ に適用すると、位相の干渉（量子干渉）が起こります。&lt;/p>
$$ |\psi_4\rangle = \text{QFT} |\psi_3\rangle = \frac{1}{\sqrt{MQ}} \sum_{y=0}^{Q-1} \sum_{k=0}^{M-1} e^{2\pi i \frac{(x_0 + kr)y}{Q}} |y\rangle $$
&lt;p>この式の和を展開すると、&lt;/p>
$$ \sum_{k=0}^{M-1} e^{2\pi i \frac{kry}{Q}} $$
&lt;p>という部分が現れます。この幾何級数の和は、$ry/Q$ が整数に近いときにのみ強め合い（Constructive Interference）、それ以外のときには相殺し合います（Destructive Interference）。&lt;/p>
&lt;p>したがって、高い確率で測定される状態 $|y\rangle$ は、&lt;/p>
$$ \frac{y}{Q} \approx \frac{c}{r} $$
&lt;p>という条件を満たす整数 $y$ となります（$c$ は何らかの整数）。&lt;/p>
&lt;h3 id="43-連分数展開による周期の特定">4.3. 連分数展開による周期の特定
&lt;/h3>&lt;p>測定によって $y$ を得た後、古典コンピュータを用いて $y/Q$ を &lt;strong>「連分数展開」&lt;/strong> （Continued Fraction Expansion）します。これにより、$y/Q$ の近似分数 $c/r$ を計算し、分母から周期 $r$ の候補を高効率に抽出することができます。&lt;/p>
&lt;hr>
&lt;h2 id="5-概念モデルの比較とパラダイムシフト">5. 概念モデルの比較とパラダイムシフト
&lt;/h2>&lt;p>GNFSとShorのアルゴリズムの違いを直感的に理解するために、Mermaid記法による概念図を示します。&lt;/p>
&lt;h3 id="量子回路によるshorのアルゴリズムの概念図">量子回路によるShorのアルゴリズムの概念図
&lt;/h3>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">graph TD
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> A[初期状態: 0...0] --&amp;gt; B[Hadamard変換で全状態の重ね合わせ]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> B --&amp;gt; C[モジュラべき乗演算 a^x mod N]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> C --&amp;gt;|量子もつれ| D[周期性を持つ状態への収縮]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> D --&amp;gt; E[量子フーリエ変換 QFT]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> E --&amp;gt;|干渉による確率増幅| F[測定: yを得る]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> F --&amp;gt; G[古典処理: 連分数展開]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> G --&amp;gt; H[周期 r の発見]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> H --&amp;gt; I[Nの素因数を算出]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> style A fill:#f9f,stroke:#333,stroke-width:2px
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> style E fill:#bbf,stroke:#333,stroke-width:2px
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> style I fill:#bfb,stroke:#333,stroke-width:2px
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="パラダイムシフトの本質">パラダイムシフトの本質
&lt;/h3>&lt;p>GNFSは &lt;strong>「数学的な空間（代数体）の中で関係式を探索する」&lt;/strong> というアプローチをとります。しかし、探索空間は桁数に対して指数関数的に拡大するため、古典コンピュータの計算能力（並列化を含めても）では、鍵長が2048ビットなどを超えると事実上解読不可能になります。&lt;/p>
&lt;p>一方、Shorのアルゴリズムは &lt;strong>「量子干渉による波の性質」&lt;/strong> を利用します。重ね合わせ状態にあるすべての計算経路を同時に評価し、QFTによって不要な答えを相殺（弱め合い）、正解となる周期の確率振幅だけを増幅（強め合い）させます。これにより、空間を探索するのではなく、 &lt;strong>「正解そのものを浮かび上がらせる」&lt;/strong> という全く異なる次元のアプローチを実現しているのです。&lt;/p>
&lt;h2 id="6-まとめ">6. まとめ
&lt;/h2>&lt;p>本記事では、古典限界の極みである &lt;strong>「GNFS」&lt;/strong> と、量子計算の力を見せつける &lt;strong>「Shorのアルゴリズム」&lt;/strong> について、それぞれの数学的背景とアルゴリズムの構造を深く比較しました。&lt;/p>
&lt;p>GNFSが多項式の選択や巨大行列の計算といった数学的技巧を凝らして準指数時間へと計算量を押し下げたのに対し、Shorのアルゴリズムは量子力学の基本原理である重ね合わせと干渉を数学的ツール（QFT）と融合させ、一気に多項式時間へとブレイクスルーを果たしました。&lt;/p>
&lt;p>現状では、実用的な規模（数千量子ビット）でShorのアルゴリズムを実行できるエラー耐性量子コンピュータ（FTQC）は存在しません。しかし、この数学的・理論的なパラダイムシフトの存在こそが、現在世界中で耐量子計算機暗号（PQC: Post-Quantum Cryptography）への移行が急がれている最大の理由なのです。&lt;/p></description></item></channel></rss>