結果
問題 | No.195 フィボナッチ数列の理解(2) |
ユーザー | rpy3cpp |
提出日時 | 2016-02-14 16:04:47 |
言語 | Python3 (3.12.2 + numpy 1.26.4 + scipy 1.12.0) |
結果 |
AC
|
実行時間 | 34 ms / 5,000 ms |
コード長 | 3,342 bytes |
コンパイル時間 | 86 ms |
コンパイル使用メモリ | 13,184 KB |
実行使用メモリ | 11,136 KB |
最終ジャッジ日時 | 2024-09-22 06:30:47 |
合計ジャッジ時間 | 1,699 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 31 ms
11,136 KB |
testcase_01 | AC | 33 ms
11,008 KB |
testcase_02 | AC | 33 ms
11,136 KB |
testcase_03 | AC | 32 ms
11,136 KB |
testcase_04 | AC | 34 ms
11,008 KB |
testcase_05 | AC | 31 ms
11,008 KB |
testcase_06 | AC | 31 ms
11,008 KB |
testcase_07 | AC | 31 ms
11,008 KB |
testcase_08 | AC | 32 ms
11,008 KB |
testcase_09 | AC | 32 ms
11,008 KB |
testcase_10 | AC | 33 ms
11,008 KB |
testcase_11 | AC | 34 ms
11,008 KB |
testcase_12 | AC | 33 ms
11,008 KB |
testcase_13 | AC | 34 ms
11,008 KB |
testcase_14 | AC | 33 ms
11,008 KB |
testcase_15 | AC | 33 ms
11,008 KB |
testcase_16 | AC | 34 ms
11,008 KB |
testcase_17 | AC | 33 ms
11,008 KB |
testcase_18 | AC | 34 ms
11,008 KB |
testcase_19 | AC | 33 ms
11,008 KB |
testcase_20 | AC | 33 ms
11,008 KB |
testcase_21 | AC | 34 ms
11,008 KB |
testcase_22 | AC | 34 ms
11,008 KB |
testcase_23 | AC | 33 ms
11,008 KB |
testcase_24 | AC | 34 ms
11,008 KB |
ソースコード
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: t = 1 + (-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))