結果
| 問題 |
No.579 3 x N グリッド上のサイクルのサイズ(hard)
|
| ユーザー |
maspy
|
| 提出日時 | 2020-05-06 18:23:41 |
| 言語 | Python3 (3.13.1 + numpy 2.2.1 + scipy 1.14.1) |
| 結果 |
AC
|
| 実行時間 | 684 ms / 2,000 ms |
| コード長 | 2,982 bytes |
| コンパイル時間 | 94 ms |
| コンパイル使用メモリ | 13,056 KB |
| 実行使用メモリ | 44,948 KB |
| 最終ジャッジ日時 | 2024-07-03 09:05:39 |
| 合計ジャッジ時間 | 44,679 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 80 |
ソースコード
import sys
import numpy as np
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines
# 頂点の代わりに辺を選ぶ
MOD = 10**9 + 7
def compute_next_status(status, vertical):
status = list(status)
deg = [0] * 4
for i, x in enumerate(status):
if x != 0:
deg[i] = 1
loop = False
for i in range(3):
if vertical & (1 << i):
deg[i] += 1
deg[i+1] += 1
if status[i] == status[i+1] != 0:
if loop:
return None
loop = True
status[i] = status[i+1] = 0
continue
if status[i] == status[i+1] == 0:
status[i] = status[i+1] = max(status) + 1
elif status[i] != 0 and status[i+1] == 0:
status[i+1] = status[i]
elif status[i+1] != 0 and status[i] == 0:
status[i] = status[i+1]
else:
n, m = status[i:i+2]
n, m = max(n, m), min(n, m)
for v in range(4):
if status[v] == m:
status[v] = n
if loop:
if any(x in [1,3] for x in deg):
return None
return (0,0,0,0)
if any(x >= 3 for x in deg):
return None
for v in range(4):
if deg[v] != 1:
status[v] = 0
for n, k in enumerate(set(status + [0])):
if k == 0:
continue
for v in range(4):
if status[v] == k:
status[v] = n
return tuple(status)
visited = set([(0,0,0,0)])
q = [(0,0,0,0)]
edges = [] # 遷移に加えて、追加した辺の本数を持たせる
popcount = [0,1,1,2,1,2,2,3]
while q:
v = q.pop()
for i in range(8):
w = compute_next_status(v, i)
if w is None:
continue
edges.append((v,w, popcount[i] + sum(x != 0 for x in w)))
if w in visited:
continue
visited.add(w)
q.append(w)
L = len(visited) + 1
A = np.zeros((2*L,2*L), dtype=object)
v_to_i = {v:i for i,v in enumerate(visited)}
i0 = v_to_i[(0,0,0,0)]
i_end = L - 1
for v,w,k in edges:
iv, iw = v_to_i[v], v_to_i[w]
if iv != i0 and iw == i0:
iw = i_end
A[2*iw, 2*iv] = 1 # 選択なし -> 選択なし
A[2*iw+1, 2*iv] = k # 選択なし -> 選択あり
A[2*iw+1,2*iv+1] = 1 # 選択あり -> 選択あり
A[2*i_end, 2*i_end] += 1
A[2*i_end+1, 2*i_end+1] += 1
def mult_mod(A, B, MOD=MOD):
mask = (1<<15) - 1
A1, A2 = A>>15, A & mask
B1, B2 = B>>15, B&mask
X = np.dot(A1, B1) % MOD
Z = np.dot(A2, B2) % MOD
Y = (np.dot(A1+A2,B1+B2)-X-Z)%MOD
return ((X<<30)+(Y<<15)+Z)%MOD
def matrix_power(A, n, MOD=MOD):
if n == 1:
return A
B = matrix_power(A, n//2)
B = mult_mod(B, B)
if n & 1:
B = mult_mod(A, B)
return B
N = int(read())
print(matrix_power(A, N + 1)[2*i_end+1, 2*i0])
maspy