https://projecteuler.net/problem=64
平方根の連分数の周期は、たぶん具体的に計算するしかないです。
まず、とすると少し見通しがよくなります。
の逆数を取ると、
となります。なので、
の場合に限り、周期1になります。
この整数部分がfだとすると、整数を引いて0以上1未満にするのにfを引いて、となります。この逆数を取ると、
となります。このように一般に
の係数は1になります。ここで、
とすると分母が1になって、周期2だとわかります。つまりs(>1)が2rの約数の時に周期2になります。たとえば、
なら、
なら周期2で、けっこう多いです。このようにある程度は周期がわかる場合がありますが、基本的には順番に計算していくしかないです。
import sys fn find_period(r: Int, s: Int) -> Int: # (sqrt(r^2+s) - a) / b var a = r var b = 1 var period = 1 while True: # 逆数を取る var b1 = (r*r + s - a*a) // b var a1 = -(a - (r + a) // b1 * b1) if b1 == 1: return period a = a1 b = b1 period += 1 fn f(N: Int) -> Int: var counter = 0 var r = 1 while True: for s in range(1, 2*r+1): var n = r*r + s if n > N: return counter var period = find_period(r, s) if period % 2 == 1: counter += 1 r += 1 fn main() raises: var args = sys.argv() var N = atol(args[1]) print(f(N))