結果
問題 | No.1839 Concatenation Matrix |
ユーザー | hitonanode |
提出日時 | 2021-12-19 19:15:28 |
言語 | Python3 (3.12.2 + numpy 1.26.4 + scipy 1.12.0) |
結果 |
TLE
|
実行時間 | - |
コード長 | 3,683 bytes |
コンパイル時間 | 444 ms |
コンパイル使用メモリ | 13,184 KB |
実行使用メモリ | 97,460 KB |
最終ジャッジ日時 | 2024-09-15 14:45:08 |
合計ジャッジ時間 | 14,990 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 520 ms
97,460 KB |
testcase_01 | AC | 517 ms
43,972 KB |
testcase_02 | AC | 520 ms
44,100 KB |
testcase_03 | AC | 525 ms
43,968 KB |
testcase_04 | AC | 520 ms
44,100 KB |
testcase_05 | AC | 517 ms
43,976 KB |
testcase_06 | AC | 524 ms
43,984 KB |
testcase_07 | AC | 568 ms
43,844 KB |
testcase_08 | AC | 678 ms
43,720 KB |
testcase_09 | AC | 769 ms
43,732 KB |
testcase_10 | AC | 3,115 ms
48,488 KB |
testcase_11 | TLE | - |
testcase_12 | -- | - |
testcase_13 | -- | - |
testcase_14 | -- | - |
testcase_15 | -- | - |
testcase_16 | -- | - |
testcase_17 | -- | - |
testcase_18 | -- | - |
ソースコード
import numpy as np class NTT: def __init__(self, D: int, MOD: int, root: int) -> None: self.md = MOD self.w = np.array([1], np.int64) self.iw = np.array([1], np.int64) while len(self.w) < 1 << (D - 1): dw = pow(root, (self.md - 1) // (len(self.w) * 4), self.md) dwinv = pow(dw, -1, self.md) self.w = np.r_[self.w, self.w * dw] % self.md self.iw = np.r_[self.iw, self.iw * dwinv] % self.md def ntt(self, mat: np.ndarray): in_shape = mat.shape n = in_shape[-1] m = n // 2 while m: mat = mat.reshape(-1, n // (m * 2), 2, m) w_use = self.w[:n // (m * 2)].reshape(1, -1, 1) y = mat[:, :, 1] * w_use % self.md mat = np.stack((mat[:, :, 0] + y, mat[:, :, 0] + self.md - y), 2) % self.md m //= 2 return mat.reshape(in_shape) def intt(self, mat: np.ndarray): in_shape = mat.shape n = in_shape[-1] m = 1 while m < n: mat = mat.reshape(-1, n // (m * 2), 2, m) iw_use = self.iw[:n // (m * 2)].reshape(1, -1, 1) mat = np.stack((mat[:, :, 0] + mat[:, :, 1], (mat[:, :, 0] + self.md - mat[:, :, 1]) * iw_use), 2) % self.md m *= 2 n_inv = pow(n, -1, self.md) return mat.reshape(in_shape) * n_inv % self.md def convolve(self, v1: np.ndarray, v2: np.ndarray) -> np.ndarray: v1 = v1.copy() v2 = v2.copy() n1, n2 = len(v1), len(v2) nret = n1 + n2 - 1 nfft = 1 while nfft < nret: nfft <<= 1 v1.resize(nfft) v2.resize(nfft) v1 = self.ntt(v1) v2 = self.ntt(v2) vret = v1 * v2 % md vret = self.intt(vret) vret.resize(nret) return vret # https://maspypy.com/%E6%95%B0%E5%AD%A6%E3%83%BBnumpy-%E9%AB%98%E9%80%9F%E3%83%95%E3%83%BC%E3%83%AA%E3%82%A8%E5%A4%89%E6%8F%9Bfft%E3%81%AB%E3%82%88%E3%82%8B%E7%95%B3%E3%81%BF%E8%BE%BC%E3%81%BF def convolve(f, g): """多項式 f, g の積を計算する。 Parameters ---------- f : np.ndarray (int64) f[i] に、x^i の係数が入っている g : np.ndarray (int64) g[i] に、x^i の係数が入っている Returns ------- h : np.ndarray f,g の積 """ # h の長さ以上の n=2^k を計算 fft_len = 1 while 2 * fft_len < len(f) + len(g) - 1: fft_len *= 2 fft_len *= 2 # フーリエ変換 Ff = np.fft.rfft(f, fft_len) Fg = np.fft.rfft(g, fft_len) # 各点積 Fh = Ff * Fg # フーリエ逆変換 h = np.fft.irfft(Fh, fft_len) # 小数になっているので、整数にまるめる h = np.rint(h).astype(np.int64) return h[:len(f) + len(g) - 1] def convolve2(f, g, p): f1, f2 = np.divmod(f, 1 << 15) g1, g2 = np.divmod(g, 1 << 15) a = convolve(f1, g1) % p c = convolve(f2, g2) % p b = (convolve(f1 + f2, g1 + g2) - (a + c)) % p h = (a << 30) + (b << 15) + c return h % p md = 998244353 # convolver = NTT(18, md, 3) N = int(input()) A = np.array(list(map(int, input().split())), dtype=np.int64) polys = [None] * (N * 2) p10 = 10 for i in range(N - 1): polys[i] = np.array([1, p10], dtype=np.int64) p10 = p10 * p10 % md l, r = 0, N - 1 while l + 1 < r: polys[r] = convolve2(polys[l], polys[l + 1], md) polys[l] = None polys[l + 1] = None r += 1 l += 2 # vs = convolver.convolve(polys[l], A) vs = convolve2(polys[l], A, md) ret = np.zeros(N, dtype=np.int64) for i, v in enumerate(vs): ret[(i + 1) % N] += v ret %= md print(*ret, sep='\n')