---
# System prepended metadata

title: 今年の整数問題（2017/01/10）
tags: [' 整数問題', 数学]

---

---
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

```