結果

問題 No.1561 connect x connect
ユーザー maspymaspy
提出日時 2021-04-11 13:31:43
言語 PyPy3
(7.3.15)
結果
TLE  
(最新)
AC  
(最初)
実行時間 -
コード長 4,148 bytes
コンパイル時間 259 ms
コンパイル使用メモリ 87,160 KB
実行使用メモリ 173,712 KB
最終ジャッジ日時 2023-09-07 13:52:58
合計ジャッジ時間 10,178 ms
ジャッジサーバーID
(参考情報)
judge11 / judge12
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 67 ms
76,032 KB
testcase_01 AC 137 ms
78,204 KB
testcase_02 AC 298 ms
81,940 KB
testcase_03 AC 70 ms
71,388 KB
testcase_04 AC 75 ms
75,320 KB
testcase_05 AC 79 ms
76,184 KB
testcase_06 AC 74 ms
71,364 KB
testcase_07 AC 71 ms
71,364 KB
testcase_08 AC 75 ms
75,756 KB
testcase_09 AC 71 ms
75,756 KB
testcase_10 AC 76 ms
76,040 KB
testcase_11 AC 137 ms
78,448 KB
testcase_12 AC 194 ms
78,992 KB
testcase_13 AC 284 ms
81,980 KB
testcase_14 AC 679 ms
91,920 KB
testcase_15 AC 677 ms
91,928 KB
testcase_16 AC 300 ms
82,116 KB
testcase_17 AC 137 ms
78,548 KB
testcase_18 AC 79 ms
76,592 KB
testcase_19 AC 783 ms
91,880 KB
testcase_20 AC 219 ms
78,764 KB
testcase_21 AC 74 ms
76,412 KB
testcase_22 AC 205 ms
79,136 KB
testcase_23 AC 72 ms
76,584 KB
testcase_24 AC 763 ms
92,256 KB
testcase_25 AC 75 ms
76,388 KB
testcase_26 TLE -
testcase_27 -- -
testcase_28 -- -
testcase_29 -- -
testcase_30 -- -
testcase_31 -- -
testcase_32 -- -
testcase_33 -- -
testcase_34 -- -
testcase_35 -- -
testcase_36 -- -
testcase_37 -- -
権限があれば一括ダウンロードができます

ソースコード

diff #

MOD = 1_000_000_007

def to(H, A):
    """
    empty col
    """
    if A == 'begin':
        yield 'begin'
    elif A == 'end':
        yield 'end'
    elif len(set(x for x in A if x >= 0)) == 1:
        yield 'end'

    if A == 'end':
        return
    _A = A
    for s in range(1, 1 << H):
        if _A == 'begin' or _A == 'end':
            A = [-1] * H
        else:
            A = list(_A)
        for i in range(H):
            if A[i] >= 0:
                A[i] += H
        for i in range(H):
            if s & 1 << i:
                A.append(i)
            else:
                A.append(-1)
        """
        横にマージ
        """
        for i in range(H):
            j = i + H
            if A[i] >= 0 and A[j] >= 0 and A[i] != A[j]:
                before = max(A[i], A[j])
                after = min(A[i], A[j])
                for k in range(H + H):
                    if A[k] == before:
                        A[k] = after
        """
        縦にマージ
        """
        for i in range(H, H + H - 1):
            j = i + 1
            if A[i] >= 0 and A[j] >= 0 and A[i] != A[j]:
                before = max(A[i], A[j])
                after = min(A[i], A[j])
                for k in range(H + H):
                    if A[k] == before:
                        A[k] = after
        if any(x >= H for x in A[:H]):
            # 孤立した連結成分が残ってしまった場合
            continue
        yield tuple(A[H:])


def flip(A):
    H = len(A)
    A = list(A[::-1])
    for i in range(H):
        if A[i] != -1:
            A[i] = H - 1 - A[i]
    for i in range(H):
        if A[i] > i:
            before = A[i]
            after = i
            for j in range(H):
                if A[j] == before:
                    A[j] = after
    return tuple(A)

def generate_graph_compress(H):
    """
    mirror reflection を同一視して、状態を圧縮する
    """
    V = ['begin', 'end']
    ID = {'begin': 0, 'end': 1}
    G = []
    for i, v in enumerate(V):
        for w in to(H, v):
            if w == 'begin' or w == 'end':
                pass
            else:
                w = min(w, flip(w))
            if w not in ID:
                ID[w] = len(V)
                V.append(w)
            j = ID[w]
            G.append((i, j))
    return len(V), G

"""
N = 436 に対して
(N,N) 行列の 10^18 乗あたりを求めることになる。厳しい。
線形漸化式を、前計算することにする。
"""

def conv(A, B):
    C = [0] * (len(A) + len(B) - 1)
    for i in range(len(A)):
        for j in range(len(B)):
            C[i + j] += A[i] * B[j]
            C[i + j] %= MOD
    return C

def coef_of_generating_function(P, Q, N):
    assert Q[0] == 1 and len(Q) == len(P) + 1

    while N:
        Q1 = Q.copy()
        for i in range(len(Q)):
            if i & 1:
                Q1[i] = -Q1[i]
        P = conv(P, Q1)[N & 1::2]
        Q = conv(Q, Q1)[::2]
        N >>= 1
    return P[0]

def find_generating_function(A):
    N = len(A)
    B = [1]
    C = [1]
    l, m, p = 0, 1, 1
    for i in range(N):
        d = A[i]
        for j in range(1, l + 1):
            d += C[j] * A[i - j]
            d %= MOD
        if d == 0:
            m += 1
            continue
        T = C.copy()
        q = pow(p, MOD - 2, MOD) * d % MOD
        if len(C) < len(B) + m:
            C += [0] * (len(B) + m - len(C))
        for j in range(len(B)):
            C[j + m] -= q * B[j]
            C[j + m] %= MOD
        if l + l <= i:
            B = T
            l, m, p = i + 1 - l, 1, d
        else:
            m += 1
    Q = C
    P = conv(A, Q)[:len(Q) - 1]
    return P, Q

def solve_small(H):
    N, G = generate_graph_compress(H)
    FRM, TO = map(list, zip(*G))
    MAX = N + N + 10
    ans = [0] * MAX
    dp = [0] * N
    dp[0] = 1
    for i in range(MAX):
        newdp = [0] * N
        for a, b in G:
            newdp[b] += dp[a]
        dp = [x % MOD for x in newdp]
        ans[i] = dp[1]
    return ans

H, W = map(int, input().split())
A = solve_small(H)
P, Q = find_generating_function(A)

print(coef_of_generating_function(P, Q, W))
0