結果
問題 | No.3082 Make Palindromic Multiple(Judge) |
ユーザー |
👑 |
提出日時 | 2025-03-29 08:48:37 |
言語 | PyPy3 (7.3.15) |
結果 |
WA
|
実行時間 | - |
コード長 | 3,729 bytes |
コンパイル時間 | 241 ms |
コンパイル使用メモリ | 82,668 KB |
実行使用メモリ | 150,012 KB |
最終ジャッジ日時 | 2025-03-29 08:49:02 |
合計ジャッジ時間 | 23,525 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 WA * 1 |
other | AC * 57 TLE * 1 -- * 13 |
ソースコード
def solve(): import sys input = sys.stdin.readline sys.setrecursionlimit(10**7) # 入力 K = int(input()) blocks = [] for _ in range(K): # 各行は「S T」という形式を仮定 # もしくは別行で与えられる場合もあるので適宜修正 line = input().split() S = line[0].strip() T = int(line[1]) blocks.append((S, T)) # ハッシュ計算のための定数 base = 10007 mod1 = 1000000007 mod2 = 1000000009 # 拡張ユークリッド互除法による逆元計算 def modinv(x, mod): return pow(x, mod-2, mod) # 幾何級数の和 : 1 + r + r^2 + ... + r^(T-1) def geo_sum(r, T, mod): if r % mod == 1: return T % mod return (pow(r, T, mod) - 1) * modinv(r - 1, mod) % mod # 各ブロックについて,順方向のハッシュと逆方向のハッシュを計算する。 # S の各文字は '0'-'9' なので,数値としては 1~10 に変換('0'を1にする等) def compute_hashes(S, mod): h = 0 for ch in S: # 数値部分:'0'からのずれ+1 h = (h * base + (ord(ch) - ord('0') + 1)) % mod return h # 各ブロックごとに,順方向ハッシュ・逆方向ハッシュ・ブロックの長さを求める # S を T 回連結したブロックのハッシュは, # H_block = H(S) * (1 + base^|S| + base^(2|S|) + ... + base^((T-1)|S|)) # とできる(mod arithmetic)。 block_data = [] # 各要素: (L, total_len, h1, h2, hr1, hr2) mod mod1, mod2 for S, T in blocks: L = len(S) tot = L * T # ブロック全体の長さ # S の順方向ハッシュ hS1 = compute_hashes(S, mod1) hS2 = compute_hashes(S, mod2) # S の逆順ハッシュ(S[::-1]) hrS1 = compute_hashes(S[::-1], mod1) hrS2 = compute_hashes(S[::-1], mod2) # 幾何級数の和の係数: 1 + base^L + base^(2L) + ... + base^((T-1)L) r1 = pow(base, L, mod1) r2 = pow(base, L, mod2) geo1 = geo_sum(r1, T, mod1) geo2 = geo_sum(r2, T, mod2) # ブロック全体のハッシュ(順方向) block_hash1 = (hS1 * geo1) % mod1 block_hash2 = (hS2 * geo2) % mod2 # ブロック全体のハッシュ(逆方向): S[::-1] を T 回連結 block_rhash1 = (hrS1 * geo1) % mod1 block_rhash2 = (hrS2 * geo2) % mod2 block_data.append((L, tot, block_hash1, block_hash2, block_rhash1, block_rhash2)) # 全体の文字列 X のハッシュを,順方向・逆方向それぞれ求める。 total_len = 0 # X の先頭からの長さ(論理的な指数) hash1 = 0 hash2 = 0 for L, tot, bh1, bh2, _, _ in block_data: # 既に構築した文字列の後ろにこのブロックを付ける. hash1 = (hash1 + bh1 * pow(base, total_len, mod1)) % mod1 hash2 = (hash2 + bh2 * pow(base, total_len, mod2)) % mod2 total_len += tot # 逆方向のハッシュ: X[::-1] = (block_K reversed) concat ... concat (block_1 reversed) rhash1 = 0 rhash2 = 0 offset = 0 for L, tot, _, _, brh1, brh2 in reversed(block_data): rhash1 = (rhash1 + brh1 * pow(base, offset, mod1)) % mod1 rhash2 = (rhash2 + brh2 * pow(base, offset, mod2)) % mod2 offset += tot # X が回文なら,順方向ハッシュと逆方向ハッシュが一致するはず if hash1 == rhash1 and hash2 == rhash2: sys.stdout.write("Yes") else: sys.stdout.write("No") if __name__ == '__main__': solve()