--- tags: 数学, 整数問題 --- 今年の整数問題(2017/01/10) ================== ## 問題 【問題1】 $6,5,6,9,29,4,29,1,61,24,\dots$ という数列の、$n$番目は$209$であり、$50$番目は$n$である。$n$はいくつか。ただし今日(2017/01/10)は私の$n$歳の誕生日です。 【問題2】 この数列の$k$番目の値を$a_k$と書くと、$k=3$は$a_k=2k$となる最小の値である($a_3=6$)。$a_k=k$となる最小の$k$を求めよ。 ## 解答 【問題1】 $n=41$ 【問題2】 $k=52892561984$ ### 解説 この数列 $\{a_i\}$ は、以下のような法則で成り立っている: + $b_i$ を $i$ と $a_i$ を10進表記で続けて記述してできる数としたとき、$b_i$ は平方数である。 + (補足)$a_i$ を10進表記で$m$桁とした場合、$b_i = 10^mi+a_i$ である。 + $a_i$ の(10進表記の)上1桁は$0$ではない。 + $a_i$ は、上記2つの条件を満たす数のうちの最小値である。 例: | $i$ | $a_i\ (b_i)$ | | --: | :-- | | $1$ | $6\ (16=4^2)$ | | $2$ | $5\ (25=5^2)$ | | $3$ | $6\ (36=6^2)$ | | $4$ | $9\ (49=7^2)$ | | $5$ | $29\ (529=23^2)$ | | $6$ | $4\ (64=8^2)$ | | $7$ | $29\ (729=27^2)$ | | $8$ | $1\ (81=9^2)$ | | $9$ | $61\ (961=31^2)$ | | $10$ | $24\ (1024=32^2)$ | | $11$ | $56\ (1156=34^2)$ | | $12$ | $1\ (121=11^2)$ | | : | : | | $24$ | $336\ (24336=156^2)$ | | : | : | 例えば $2401=49^2$ だが、$a_{24}$ は $1$ ではない($241$ は平方数ではない)。一方で $a_{240}=1$ である。 【問題1】は、$a_{50}$ を求めればOK。その値($m$と置く)で $a_m=209$ であることを確認(検算)すれば良い。 一般の $n$ について $a_n$ を求めるアルゴリズム(概要)は、以下の通りとなる: 1. $d := 10$, $m := 10n + 1$ と置く 2. $r := \lceil \sqrt{m} \rceil^2 - dn$ と置く 3. $r < d$ ならば、$r$ を返して終了。 4. $d \leftarrow 10d$, $m \leftarrow 10m$ として、2. に戻る [Julia](https://julialang.org) で記述したコード例がこちら: ```julia function an(n::T) where {T<:Integer} d = n10 = T(10) m = n * n10 + one(T) while true r = ceil(T, sqrt(m)) ^ 2 - n * d if r < d return r end d *= n10 m *= n10 end end ``` これにより、`an(50) # => 41`($a_{50}=41$)が得られる。また `an(41) # => 209`($a_{41} = 209$)も確かめられる。 【問題2】は、このアルゴリズムを用いて $a_k=k$ となる $k$ を探すのだが、それを愚直に $k=1$ から順に実施すると全く終了しない。 $a_k=k$ ということは、$k$ を $m$桁とすると、$(10^m+1)k$ が平方数になる、ということである。よって少なくとも $10^m+1$ が平方因子をもたなければならない($\because$ $10^m+1$ が平方因子を持たない($\Leftrightarrow$素因数分解したときの各素数の冪数がすべて$1$ の)場合、$(10^m+1)k$ が平方数であるためには $k$ が $10^m+1$ の倍数である必要があるが、この時 $k$ は $m+1$ 桁以上になる)。 これを利用して $m$ の候補を絞り込んで $k$ を探せば良い。 詳細は省略するが、例えば [Julia](https://julialang.org) なら以下のようなコードを記述すれば求解出来る(要:`Primes.jl`)。 ```julia # Pkg.add("Primes") using Primes function solve(verbose=false) n1 = big"1" n10 = big"10" i = n1 while true i *= n10 # = 10^m q = i + n1 # = 10^m + 1 pd = factor(q) # 素因数分解(要:`Primes.jl`) if any(v > 1 for v ∈ values(pd)) r = prod(v == 1 ? p : p ^ ((v + 1) ÷ 2) for (p, v) ∈ pd) l = r * r % i d = isqrt(i ÷ n10 ÷ l) r *= d + n1 k_cand = r * r ÷ q # ← 10^(m-1) ≤ k < 10^m かつ (10^m + 1)k が平方数となるような k の最小値 for k = [k_cand, 4k_cand, 9k_cand] if k >= i break elseif an(k) == k if verbose println("a(", k, ") = ", k, " : O") end return k elseif verbose println("a(", k, ") = ", an(k), " : X") end end end end end ``` `solve(true)` とすると、以下のように途中経過も含めて求解された結果が表示される。 ```jlcon julia> solve(true) a(13223140496) = 9685186064 : X a(52892561984) = 52892561984 : O 52892561984 ```