結果
| 問題 | No.3174 勝ち残りじゃんけん |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2025-03-03 00:30:34 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
AC
|
| 実行時間 | 259 ms / 2,000 ms |
| コード長 | 2,846 bytes |
| 記録 | |
| コンパイル時間 | 652 ms |
| コンパイル使用メモリ | 82,840 KB |
| 実行使用メモリ | 81,536 KB |
| 最終ジャッジ日時 | 2025-03-03 00:30:39 |
| 合計ジャッジ時間 | 4,688 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 17 |
ソースコード
#references: https://qiita.com/izu_nori/items/1c5cdef0500ffa0276f5
MOD = 998244353 # : 119*2**23+1
K, M, W = 119, 23, 31 # W : 2のM乗根
class NTT:
def __init__(self):
# ws[i] = 1の2^i乗根 (31**(2**23) = 1 mod 998244353)
self.ws = [pow(W,2**i,MOD) for i in range(M,-1,-1)]
# inverse of ws
self.iws = [pow(w,MOD-2,MOD) for w in self.ws]
def polymul_ntt(self,f,g):
nf = len(f)
ng = len(g)
m = nf+ng-1
n = 2**(m-1).bit_length()
f = [x % MOD for x in f]+[0]*(n-nf) # 0-padding
g = [x % MOD for x in g]+[0]*(n-ng) # 0-padding
self.ntt(f) # 実装予定
self.ntt(g)
for i in range(n):
f[i] = f[i]*g[i]%MOD
self.intt(f) # 実装予定
return f[:m]
def _ntt(self, A, tws): # len(A) must be a power of 2
if len(A) == 1:
return A
B0 = self._ntt(A[::2], tws) # 再帰計算
B1 = self._ntt(A[1::2], tws)
k = (len(A)-1).bit_length()
res = [0]*len(A)
r = 1<<(k-1)
wi = 1
w = tws[k]
for i,(b0,b1) in enumerate(zip(B0,B1)): # バタフライ演算
res[i] = (b0 + b1 * wi) % MOD
res[i+r] = (b0 - b1 * wi) % MOD
wi = (wi*w) % MOD
return res
def ntt(self, A):
A[:] = self._ntt(A, self.ws)
def intt(self, A):
ni = pow(len(A), MOD-2, MOD)
A[:] = [x*ni%MOD for x in self._ntt(A, self.iws)] # 結果をinplaceに格納
ntt = NTT()
# 入力を受け取る
N = int(input())
# 階乗とその逆数を計算
fact = [0] * (N + 1)
inv = [0] * (N + 1)
fact[0] = 1
for i in range(1, N + 1, 1):
fact[i] = (i * fact[i - 1]) % MOD
inv[N] = pow(fact[N], -1, MOD)
for i in range(N, 0, -1):
inv[i - 1] = (inv[i] * i) % MOD
# あいこの場合の数を3で割ったものの逆数
coef = [0] * (N + 1)
pow2 = 2
for i in range(2, N + 1, 1):
pow2 += pow2
if pow2 >= MOD: pow2 -= MOD
coef[i] = pow(pow2 - 2, -1, MOD)
# ちょうどN - i人になるときの確率とN - iの階乗とあいこの場合の数の逆数をかけたもの
dp = [0] * N
dp[0] = fact[N] * coef[N] % MOD
# オンラインNTT
def online_ntt(l, r):
if r <= l + 1: return
mid = (l + r) // 2
online_ntt(l, mid)
A = [dp[i] for i in range(l, mid)]
B = [inv[i] for i in range(r - l)]
C = ntt.polymul_ntt(A, B)
for i in range(mid, r):
dp[i] += C[i - l] * coef[N - i] % MOD
if dp[i] >= MOD: dp[i] -= MOD
online_ntt(mid, r)
online_ntt(0, N)
# 答えを計算
ans = [0] * N
total, pow3, div3 = 0, pow(3, N - 1, MOD), (MOD + 1) // 3
for i in range(N):
ans[N - 1 - i] = total
total += (dp[i] * inv[N - i]) % MOD * pow3 % MOD
if total >= MOD: total -= MOD
pow3 *= div3
pow3 %= MOD
# 答えを出力
print(*ans)