結果
| 問題 |
No.195 フィボナッチ数列の理解(2)
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2016-02-14 16:03:12 |
| 言語 | Python3 (3.13.1 + numpy 2.2.1 + scipy 1.14.1) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 3,403 bytes |
| コンパイル時間 | 91 ms |
| コンパイル使用メモリ | 13,056 KB |
| 実行使用メモリ | 11,136 KB |
| 最終ジャッジ日時 | 2024-09-22 06:30:43 |
| 合計ジャッジ時間 | 1,788 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 20 WA * 2 |
ソースコード
def gcd_ext(m: int, n: int) -> (int, int, int):
'''拡張ユークリッドの互除法
mx + ny = gcd(m, n)
となる、gcd(m, n), x, y を返す。
'''
x, y, u, v = 1, 0, 0, 1
while n:
k, m = divmod(m, n)
m, n = n, m
x, y, u, v = u, v, x - u * k, y - v * k
return m, x, y
def fibs(n):
a = 1
b = 0
result = [a]
for i in range(n - 1):
a, b = b, a + b
result.append(a)
return result
def solve(X, Y, Z):
xyz = set([X, Y, Z])
length = len(xyz)
if length == 3:
return solve3(X, Y, Z)
elif length == 2:
return solve2(*xyz)
else:
return solve1(X)
def solve1(X):
''' X = 15 のときに上手くいかない。
'''
if X == 1:
return 1, 1
N = 50
fib = fibs(N)
record = (float('inf'), float('inf'))
for fi, gi in zip(fib[2:], fib[3:]):
# fi * A + gi * B = X となる A, B で辞書順最小を求めたい。
gcdfg, a, b = gcd_ext(fi, gi)
q, r = divmod(X, gcdfg)
if r:
continue
A, B = findAB1(a * q, b * q, gi*gcdfg, fi*gcdfg)
if A > 0 and (A, B) < record:
record = (A, B)
if record != (float('inf'), float('inf')):
return record
else:
return (-1, )
def findAB1(a, b, da, db):
'''
A = a + t * da
B = b - t * db
B > 0
A > 0
のとき、A を最小とする t を求め、そのときの A, B を返す。
条件を満たす A, B が無いときは、0, 0 を返す。
a + t * da > 0
t > -a/da
b - t * db > 0
t < b/db
b/db > t > -a/da
'''
if a > 0:
if a % da:
t = - (a // da)
else:
t = 1 - (a // da)
else:
if a % da:
t = 1 + (-a)//da
else:
t = (-a)//da
A = a + t * da
B = b - t * db
if A > 0 and B > 0:
return A, B
else:
return 0, 0
def solve2(X, Y):
return solve3(X, Y, Y)
def solve3(X, Y, Z):
N = 50
fib = fibs(N)
record = (float('inf'), float('inf'))
for i in range(N - 1):
for j in range(N - 1):
if i == j:
continue
A, B = findAB3(i, j, X, Y, fib)
if A and (A, B) < record and is_valid(A, B, fib, Z):
record = (A, B)
if record != (float('inf'), float('inf')):
return record
else:
return (-1, )
def findAB3(i, j, X, Y, fib):
'''
fi * A + gi * B = X
fj * A + gj * B = Y
となる 正整数 A, B を求める。
fi*fj * A + gi*fj * B = X*fj
fi*fj * A + gj*fi * B = Y*fi
(gi*fj - gj*fi) * B = X*fj - Y*fi
B = -(fj*X - fi*Y)/(fi*gj - fj*gi)
A = (gj*X - gi*Y)/(fi*gj - fj*gi)
'''
fi = fib[i]
gi = fib[i + 1]
fj = fib[j]
gj = fib[j + 1]
det = fi * gj - fj * gi
if det == 0:
return 0, 0
A, ra = divmod(gj * X - gi * Y, det)
B, rb = divmod(-(fj * X - fi * Y), det)
if A <= 0 or B <= 0 or ra or rb:
return 0, 0
return A, B
def is_valid(A, B, fib, Z):
'''
fib[i] * A + fib[i + 1] * B = Z
となる i が存在するか調べる。
'''
for fi, gi in zip(fib, fib[1:]):
if fi * A + gi * B == Z:
return True
return False
if __name__ == '__main__':
X, Y, Z = map(int, input().split())
print(*solve(X, Y, Z))