結果
問題 | No.3117 Reversible Tile |
ユーザー |
|
提出日時 | 2025-04-20 12:58:35 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 169 ms / 3,000 ms |
コード長 | 3,515 bytes |
コンパイル時間 | 2,323 ms |
コンパイル使用メモリ | 199,104 KB |
実行使用メモリ | 7,848 KB |
最終ジャッジ日時 | 2025-04-20 12:58:41 |
合計ジャッジ時間 | 4,944 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 24 |
ソースコード
#include <bits/stdc++.h> using namespace std; using int64 = long long; const int MOD = 998244353; const int INV2 = (MOD + 1) / 2; // 2^{-1} mod MOD inline void addmod(int &a, int b) { int s = a + b; if (s >= MOD) s -= MOD; a = s; } inline void submod(int &a, int b) { int s = a - b; if (s < 0) s += MOD; a = s; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N, M; cin >> N >> M; vector<int> A(N); for (int &x : A) cin >> x; const int OFF = N + 1; // 0 が配列中央に来るようオフセット const int SZ = 2 * N + 3; // z ∈ [-(N+1), N+1] /* dp[p][t][z] を 4 本の 1D 配列で持つ p = 0/1 (現在の P_i), t = 0/1 (dot parity) */ vector<int> p0e(SZ), p0o(SZ), p1e(SZ), p1o(SZ); vector<int> c0e(SZ), c0o(SZ), c1e(SZ), c1o(SZ); p0e[OFF + 1] = 1; // i = 0 の初期 (z = 1, P_0 = 0, parity even) for (int i = 1; i <= N; ++i) { const int Ai = A[i - 1]; const int lowPrev = OFF - i; const int highPrev = OFF + i; const int lowCurr = OFF - (i + 1); const int highCurr = OFF + (i + 1); /* 配列クリア (次に使う範囲だけ) */ for (int idx = lowCurr; idx <= highCurr; ++idx) c0e[idx] = c0o[idx] = c1e[idx] = c1o[idx] = 0; for (int idx = lowPrev; idx <= highPrev; ++idx) { int v; /* p = 0, t even */ if ((v = p0e[idx])) { addmod(c0e[idx + 1], v); // P_{i+1}=0 if (Ai) addmod(c1o[idx - 1], v); // P_{i+1}=1, parity flips else addmod(c1e[idx - 1], v); } /* p = 0, t odd */ if ((v = p0o[idx])) { addmod(c0o[idx + 1], v); if (Ai) addmod(c1e[idx - 1], v); else addmod(c1o[idx - 1], v); } /* p = 1, t even */ if ((v = p1e[idx])) { if (Ai) addmod(c0o[idx + 1], v); else addmod(c0e[idx + 1], v); addmod(c1e[idx - 1], v); } /* p = 1, t odd */ if ((v = p1o[idx])) { if (Ai) addmod(c0e[idx + 1], v); else addmod(c0o[idx + 1], v); addmod(c1o[idx - 1], v); } } swap(p0e, c0e); swap(p0o, c0o); swap(p1e, c1e); swap(p1o, c1o); } /* 2^{-N} mod MOD */ int pow2N = 1; for (int i = 0; i < N; ++i) pow2N = (pow2N * 2LL) % MOD; int inv2N = 1; int e = MOD - 2, base = pow2N; while (e) { if (e & 1) inv2N = (int64)inv2N * base % MOD; base = (int64)base * base % MOD; e >>= 1; } int64 answer = 0; for (int idx = OFF - (N + 1); idx <= OFF + (N + 1); ++idx) { int d = idx - OFF; int even = (p0e[idx] + p1e[idx]) % MOD; int odd = (p0o[idx] + p1o[idx]) % MOD; int Bd = even - odd; if (Bd < 0) Bd += MOD; if (Bd == 0) continue; /* S(d) = ((d^2 - (N+1))/2) mod MOD */ int64 Sd = ( ( (int64)d * d - (N + 1) ) % MOD + MOD ) % MOD; Sd = Sd * INV2 % MOD; int64 powS = 1, baseS = Sd; int m = M; while (m) { if (m & 1) powS = powS * baseS % MOD; baseS = baseS * baseS % MOD; m >>= 1; } answer = (answer + Bd * powS) % MOD; } answer = answer * inv2N % MOD; cout << answer << '\n'; return 0; }