結果
| 問題 |
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()