結果
問題 |
No.5021 Addition Pyramid
|
ユーザー |
![]() |
提出日時 | 2025-02-25 21:32:24 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 1,647 ms / 2,000 ms |
コード長 | 3,009 bytes |
コンパイル時間 | 421 ms |
コンパイル使用メモリ | 82,584 KB |
実行使用メモリ | 79,560 KB |
スコア | 2,548,813 |
最終ジャッジ日時 | 2025-02-25 21:33:51 |
合計ジャッジ時間 | 86,678 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge6 |
純コード判定しない問題か言語 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 50 |
ソースコード
from random import randint, choice import math import time import random start = time.time() n = int(input()) a = [list(map(int, input().split())) for _ in range(n)] mod = 10**8 def compute_A(candidate): """candidate から A を構成(リストの長さを固定して高速化)""" A = [0] * (n + 1) A[0] = candidate[0] last_a = a[-1] mod_val = mod for i in range(n): A[i + 1] = (last_a[i] - A[i] + candidate[i + 1]) % mod_val return A def score_from_candidate(candidate): """ compute_A(candidate) に基づいて誤差(gosa)を計算。 各段の誤差は abs(a[i][j] - computed_value) を mod を考慮して計算し、 その最大値を返します(誤差が小さいほど良い)。 """ A = compute_A(candidate) mod_val = mod gosa = 0 d = A # 下から上へ再帰的に計算(元のコードと同じ仕様) for i in range(n - 2, 0, -1): ai = a[i] # 行 i の値をローカル参照 ndp = [0] * i for j in range(i): s = d[j] + d[j - 1] x = s % mod_val ndp[j] = x # 誤差を mod を考慮して計算 diff_val = x - ai[j] if diff_val < 0: diff_val = -diff_val # mod 周りの距離に直す diff_val = diff_val if diff_val < mod_val - diff_val else mod_val - diff_val if diff_val > gosa: gosa = diff_val d = ndp return gosa # 初期候補解の生成(candidate[0]: 0~mod-1、candidate[1..n]: 計算で決定) candidate = [randint(0, mod - 1)] for i in range(n): candidate.append((a[-1][i] - candidate[-1]) % mod) current_score = score_from_candidate(candidate) best_score = current_score best_candidate = candidate[:] # 焼きなましのパラメータ T0 = 1e5 T_end = 1e-3 TIME_LIMIT = 1.6 while time.time() - start < TIME_LIMIT: t = time.time() - start T = T0 * ((T_end / T0) ** (t / TIME_LIMIT)) new_candidate = candidate[:] # candidate のコピー idx = randint(0, n) # candidate のインデックスは 0~n if idx == 0: delta = randint(-1000, 1000) new_candidate[0] = (new_candidate[0] + delta) % mod else: delta = choice([-1, 1]) new_candidate[idx] += delta if new_candidate[idx] < 0: new_candidate[idx] = 0 elif new_candidate[idx] > 10: new_candidate[idx] = 10 new_score = score_from_candidate(new_candidate) diff = new_score - current_score # 誤差最小化なので、diff が正なら悪化 # 改善(diff <= 0)の場合は必ず採用。劣化の場合は exp(-diff/T) の確率で採用。 if diff <= 0 or random.random() < math.exp(-diff / T): candidate = new_candidate current_score = new_score if new_score < best_score: best_score = new_score best_candidate = new_candidate[:] print(*compute_A(best_candidate))