結果
問題 |
No.5021 Addition Pyramid
|
ユーザー |
![]() |
提出日時 | 2025-02-25 23:08:15 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 129 ms / 2,000 ms |
コード長 | 3,610 bytes |
コンパイル時間 | 574 ms |
コンパイル使用メモリ | 82,428 KB |
実行使用メモリ | 78,112 KB |
スコア | 2,004,118 |
最終ジャッジ日時 | 2025-02-25 23:08:24 |
合計ジャッジ時間 | 8,212 ms |
ジャッジサーバーID (参考情報) |
judge6 / judge2 |
純コード判定しない問題か言語 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 50 |
ソースコード
#!/usr/bin/env python3 mod = 10**8 def error(x, y): """ x と y の誤差(循環距離:|x-y| と mod - |x-y| の小さい方) """ diff = abs(x - y) return min(diff, mod - diff) def compute_row(prev_row, pivot_index, pivot_val): """ prev_row: 上段の値(長さ n のリスト) pivot_index: 新たな行(長さ n+1)の自由変数とするセルのインデックス (0-indexed) pivot_val: そのセルに設定する値 新たな行 new_row を,右側: new_row[j+1] = (prev_row[j] - new_row[j]) mod mod, 左側: new_row[j-1] = (prev_row[j-1] - new_row[j]) mod mod により決定する. """ n = len(prev_row) L = n + 1 new_row = [None] * L new_row[pivot_index] = pivot_val # 右側を決定 for j in range(pivot_index, L - 1): new_row[j + 1] = (prev_row[j] - new_row[j]) % mod # 左側を決定 for j in range(pivot_index, 0, -1): new_row[j - 1] = (prev_row[j - 1] - new_row[j]) % mod return new_row def beam_search(a, beam_width=10, delta_range=5): """ a: 目標ピラミッド(各段の値 a[i][j],0-indexed.第0段は1要素,...,第N-1段は N 要素) beam_width: 各段で保持する候補数 delta_range: 自由変数(中央のセル)の候補として,ターゲット値からのずれ [-delta_range, delta_range] を試す ビームサーチで各段を決定し,最終的な底辺(最下段の候補)を返す. 各段における候補の評価は,その段での各セルの誤差(error 関数) とこれまでの最大誤差の最大値を用いる(最小化したい)。 """ N = len(a) # beam の各候補は (current_row, current_max_error) のタプル. # 最上段は確定: [a[0][0]] で誤差は 0 とする. beam = [ ([a[0][0]], 0) ] # 1段目から下段へ拡張していく for i in range(1, N): new_beam = [] L = i + 1 # 新たな行の自由変数として,中央 (1-indexed で (L+1)//2 番目) を使う pivot_index = (L + 1) // 2 - 1 for row, curr_max_err in beam: # ターゲットとなる自由変数の値 target_pivot = a[i][pivot_index] # ターゲット値の前後 delta_range 内の候補を試す for delta in range(-delta_range, delta_range + 1): pivot_val = (target_pivot + delta) % mod new_row = compute_row(row, pivot_index, pivot_val) # 新たな行の各セルでの誤差を計算 row_errors = [error(new_row[j], a[i][j]) for j in range(L)] new_max_err = max(curr_max_err, max(row_errors)) new_beam.append((new_row, new_max_err)) # 評価の低いもの(誤差が小さいもの)をビーム幅内に残す new_beam.sort(key=lambda x: x[1]) beam = new_beam[:beam_width] # 最終的に,ビーム中で最も誤差の低い候補の底辺を返す best_candidate = min(beam, key=lambda x: x[1]) return best_candidate[0] def main(): import sys data = sys.stdin.read().strip().split() if not data: return N = int(data[0]) a = [] index = 1 # 各段は 1, 2, …, N 個の整数 for i in range(1, N + 1): row = [] for _ in range(i): row.append(int(data[index])) index += 1 a.append(row) bottom_row = beam_search(a, beam_width=10, delta_range=5) for num in bottom_row: print(num) if __name__ == '__main__': main()