結果

問題 No.1839 Concatenation Matrix
ユーザー 👑 hitonanodehitonanode
提出日時 2021-12-19 19:15:28
言語 Python3
(3.12.2 + numpy 1.26.4 + scipy 1.12.0)
結果
TLE  
実行時間 -
コード長 3,683 bytes
コンパイル時間 638 ms
コンパイル使用メモリ 11,312 KB
実行使用メモリ 52,820 KB
最終ジャッジ日時 2023-10-13 18:58:01
合計ジャッジ時間 10,051 ms
ジャッジサーバーID
(参考情報)
judge12 / judge11
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 142 ms
35,092 KB
testcase_01 AC 143 ms
30,052 KB
testcase_02 AC 145 ms
30,060 KB
testcase_03 AC 144 ms
29,904 KB
testcase_04 AC 143 ms
30,072 KB
testcase_05 AC 139 ms
30,044 KB
testcase_06 AC 140 ms
30,020 KB
testcase_07 AC 180 ms
30,116 KB
testcase_08 AC 295 ms
30,756 KB
testcase_09 AC 372 ms
31,116 KB
testcase_10 AC 2,474 ms
39,952 KB
testcase_11 TLE -
testcase_12 -- -
testcase_13 -- -
testcase_14 -- -
testcase_15 -- -
testcase_16 -- -
testcase_17 -- -
testcase_18 -- -
権限があれば一括ダウンロードができます

ソースコード

diff #

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')
0