ヨセフスの問題

ヨセフスの問題（ヨセフスのもんだい、英: Josephus problem）は、数論的な問題であるが、ストーリー仕立であるといった点は数学パズル的でもある。ジョセファスの問題とも。アプローチにもバリエーションがある。 n {\displaystyle n} 人の人間が円を描くように並び、処刑されるのを待っている。最初の人をスキップし、さらに k − 2 {\displaystyle k-2} 人をスキップし（つまり、 k − 1 {\displaystyle k-1} 人をスキップして k番目の人に到達する）、k番目の人を処刑する。そしてそこから、再度 k − 1 {\displaystyle k-1} 人をスキップして k番目の人を処刑する。これを延々と続け（円は徐々に小さくなっていく）、最後に残った1人を釈放する。 問題は、 n {\displaystyle n} と k {\displaystyle k} が与えられたとき、起点をどこにしたら特定の人を最後まで残せるかである。 ヨセフスの問題は、ヘゲシッポスを名乗った人物(便宜上偽ヘゲシッポス（英語版）と呼ばれる)が紀元370年ごろに『ユダヤ戦記』（フラウィウス・ヨセフス）をもとに書いた次のような問題が起源とされている。 「ユダヤ人はローマに反抗して独立戦争を起こしたときのこと、ユダヤ側の総司令官ヨセフスは、ヨタパタの町に籠城したが、ローマ軍に包囲され46日で陥落した。同志40人と洞穴に逃れたが食料も尽きてきた。衆議は降伏を拒否し自決することで決着したが、ヨセフスと彼の友人の2人は何とか生きのびたいと思っていた。いよいよ集団自決をする段になって、ヨセフスはある方法を提案した。それは、全員を円形に並べ、3番目に位置する者が他の同志に殺してもらい、これを繰り返す。最後の一人は自殺をするというものであった。この提案にみんなが賛成したので、ヨセフスと友人は16番目と31番目に位置して助かった。」 この話はヨセフスの『ユダヤ戦記』を見ると、「ヨセフスの問題」方式をとったこと以外はそのままだという。 17世紀ごろの書による。これも「ヨセフスの問題」とよばれることが多い。 「あるとき、キリスト教徒15人と異教徒であるトルコ人15人の乗る船が難破した。積荷を捨てて船を軽くしたが、まだ危険であった。ここで、船長は、15人は犠牲となって海に飛び込んでほしいといい、乗客を次のように輪に並べた。まず、キリスト教徒13人、トルコ人15人を環状に並べ、船長が数えて9人目ごとに海へ身を投じることとした。そして、うまく並べキリスト教徒全員を助けた。」 日本では、同様な話を、「継子算法」とか「ままこ立て」と呼んでいる。室町時代の本の中に、鎌倉末期に編纂したものと考えられている『吾妻鏡』をもとに、「西行法師が、源頼朝からもらった銀の眠り猫を、頼朝邸の門前で遊んでいた子に『継子算法』の要領であげてしまったと載っている。『徒然草』（兼好法師）や、『塵劫記』（吉田光由）にあるほか、関孝和も研究したことが伝わっている。考案者は不明。 まず、 k = 2 {\displaystyle k=2} の場合の解法を示す（ k ≠ 2 {\displaystyle k\neq 2} の場合については、概要を後述）。ここでは再帰的な解法を示す。 n {\displaystyle n} 人で始める場合の生き残り（の番号）を返す関数を f ( n ) {\displaystyle f(n)} とする（ k = 2 {\displaystyle k=2} ）。最初の1周で、全ての偶数番号の人が処刑される。2周目で、新たな2番目の人が処刑され、さらに新たな4番目の人が処刑され、と続く。最初の人数が偶数の場合、2周目で x {\displaystyle x} 番目の人は1周目では 2 x − 1 {\displaystyle 2x-1} 番目に位置している（ x {\displaystyle x} は任意）。したがって、 f ( n ) {\displaystyle f(n)} 番目の人は最初は 2 f ( n ) − 1 {\displaystyle 2f(n)-1} 番目に位置している。このことから、次の漸化式が得られる。 f ( 2 n ) = 2 f ( n ) − 1 {\displaystyle f(2n)=2f(n)-1\,} 最初の人数が奇数の場合、1周目の最後に1番の人が処刑される。その後、2周目では新たな2番目の人が処刑され、新たな4番目の人が処刑され…と続く。この場合、 x {\displaystyle x} 番目の人は最初は 2 x + 1 {\displaystyle 2x+1} 番目に位置していたことになる。以上から次の漸化式が得られる。 f ( 2 n + 1 ) = 2 f ( n ) + 1 {\displaystyle f(2n+1)=2f(n)+1\,} n {\displaystyle n} とそれに対応する f ( n ) {\displaystyle f(n)} の値を表にしてみると、次のようなパターンが出現する。 これを見ると、 f ( n ) {\displaystyle f(n)} は奇数の増加する数列であり、インデックス n が 2 のべき乗のときに f ( n ) = 1 {\displaystyle f(n)=1} にリセットされると思われる。したがって、 n = 2 m + l {\displaystyle n=2^{m}+l} かつ 0 ≤ l < 2 m {\displaystyle 0\leq l<2^{m}} となるような m と l を選択したとき、 f ( n ) = 2 ⋅ l + 1 {\displaystyle f(n)=2\cdot l+1} となる。上の表にある値は、この式に当てはまる。しかし、数学では厳密な証明が求められる。以下に帰納法による証明を示す。 定理: n = 2 m + l {\displaystyle n=2^{m}+l} かつ 0 ≤ l < 2 m {\displaystyle 0\leq l<2^{m}} なら、 f ( n ) = 2 l + 1 {\displaystyle f(n)=2l+1} である。 証明: n {\displaystyle n} についての数学的帰納法を用いる。まず、 n = 1 {\displaystyle n=1} では真である。 n {\displaystyle n} が偶数の場合と奇数の場合に分けて考える。 n {\displaystyle n} が偶数の場合、 n / 2 = 2 m 1 + l 1 {\displaystyle n/2=2^{m_{1}}+l_{1}} かつ 0 ≤ l 1 < 2 m 1 {\displaystyle 0\leq l_{1}<2^{m_{1}}} となるよう l 1 {\displaystyle l_{1}} と m 1 {\displaystyle m_{1}} を選択する。ここで、 l 1 = l / 2 {\displaystyle l_{1}=l/2} である。したがって、上述の漸化式から f ( n ) = 2 f ( n / 2 ) − 1 = 2 ( ( 2 l 1 ) + 1 ) − 1 = 2 l + 1 {\displaystyle f(n)=2f(n/2)-1=2((2l_{1})+1)-1=2l+1} となり、この2番目の等号は帰納仮説によるものである。 n {\displaystyle n} が奇数の場合、 ( n − 1 ) / 2 = 2 m 1 + l 1 {\displaystyle (n-1)/2=2^{m_{1}}+l_{1}} かつ 0 ≤ l 1 < 2 m 1 {\displaystyle 0\leq l_{1}<2^{m_{1}}} となるよう l 1 {\displaystyle l_{1}} と m 1 {\displaystyle m_{1}} を選択する。ここで、 l 1 = ( l − 1 ) / 2 {\displaystyle l_{1}=(l-1)/2} である。したがって、 f ( n ) = 2 f ( ( n − 1 ) / 2 ) + 1 = 2 ( ( 2 l 1 ) + 1 ) + 1 = 2 l + 1 {\displaystyle f(n)=2f((n-1)/2)+1=2((2l_{1})+1)+1=2l+1} となり、この2番目の等号は帰納仮説によるものである。（証明終） 最も簡潔な解法は二進法で n {\displaystyle n} を表す方法である。 f ( n ) {\displaystyle f(n)} は n {\displaystyle n} を1ビット左に循環シフトさせることで得られる。 n {\displaystyle n} を二進法で表したものを n = b 0 b 1 b 2 b 3 … b m {\displaystyle n=b_{0}b_{1}b_{2}b_{3}\dots b_{m}} としたとき、解は f ( n ) = b 1 b 2 b 3 … b m b 0 {\displaystyle f(n)=b_{1}b_{2}b_{3}\dots b_{m}b_{0}} となる。これの証明は n {\displaystyle n} を 2 m + l {\displaystyle 2^{m}+l} と表現する方法を使って得られる。 k を限定しない問題の最も簡単な解法は、動的計画法を使ったものである。次のような漸化式を用いる。 f ( n , k ) = ( f ( n − 1 , k ) + k ) mod n {\displaystyle f(n,k)=(f(n-1,k)+k){\bmod {n}}} 、 ただし f ( 1 , k ) = 0 {\displaystyle f(1,k)=0} これは、 n − 1 {\displaystyle n-1} から n {\displaystyle n} に増やしたときに生存者の番号がどう変化するかを考えれば明らかである。この手法の計算量は O ( n ) {\displaystyle O(n)} だが、 k {\displaystyle k} が小さく n {\displaystyle n} が大きい場合にはもっと効率的な手法がある。それは、最初のステップで k番目、2k番目、…、 ⌊ n / k ⌋ {\displaystyle \lfloor n/k\rfloor } 番目の人を処刑し、番号付けを変更するというもので、 O ( k log ⁡ n ) {\displaystyle O(k\log n)} になる。