結果
問題 |
No.3138 Minimum Bracket Subsequence
|
ユーザー |
👑 ![]() |
提出日時 | 2025-05-02 18:28:49 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 44 ms / 2,000 ms |
コード長 | 2,710 bytes |
コンパイル時間 | 2,290 ms |
コンパイル使用メモリ | 195,296 KB |
実行使用メモリ | 11,740 KB |
最終ジャッジ日時 | 2025-05-02 18:28:54 |
合計ジャッジ時間 | 4,873 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 36 |
ソースコード
#include <bits/stdc++.h> using namespace std; using int64 = long long; const int64 MOD = 998244353; const int MAXK = 500000; // K ≤ 5e5 /* ----- modular helpers ----- */ inline int64 mul_mod(int64 a, int64 b) { return (static_cast<__int128>(a) * b) % MOD; } int64 mod_pow(int64 a, unsigned long long e) { int64 r = 1; while (e) { if (e & 1) r = mul_mod(r, a); a = mul_mod(a, a); e >>= 1; } return r; } /* ----- factorial / inverse factorial ----- */ int64 fact[MAXK + 1], inv_fact[MAXK + 1]; void init_fact() { fact[0] = 1; for (int i = 1; i <= MAXK; ++i) fact[i] = mul_mod(fact[i - 1], i); inv_fact[MAXK] = mod_pow(fact[MAXK], MOD - 2); for (int i = MAXK; i >= 1; --i) inv_fact[i - 1] = mul_mod(inv_fact[i], i); } /* 単体逆元: 1/k (k≥1, k≤MAXK) */ inline int64 inv_num(int k) { // k >= 1 return mul_mod(fact[k - 1], inv_fact[k]); } /* ----- C(n,k) (k ≤ 5e5, n ≤ 1e18) ----- */ int64 nCk_large(unsigned long long n, int k) { if (k < 0 || static_cast<unsigned long long>(k) > n) return 0; k = min<unsigned long long>(k, n - k); int64 res = 1; for (int i = 0; i < k; ++i) res = mul_mod(res, (n - i) % MOD); res = mul_mod(res, inv_fact[k]); return res; } /* ----- main ----- */ int main() { ios::sync_with_stdio(false); cin.tie(nullptr); unsigned long long N; // up to 1e18 int K; string S; if (!(cin >> N >> K >> S)) return 0; init_fact(); const int half = K / 2; bool close_in_first = false; for (int i = 0; i < half; ++i) if (S[i] == ')') { close_in_first = true; break; } int64 ans; if (close_in_first) { /* ---------- Case 1 ---------- */ int l = 0; // first ')' while (S[l] != ')') ++l; int r = K - 1; // last '(' while (S[r] != '(') --r; int d = r - l; // distance to squeeze unsigned long long n2 = N - d; int k2 = K - d; // ≤ K ans = nCk_large(n2, k2); } else { /* ---------- Case 2 ---------- */ const int64 two_pow_N = mod_pow(2, N); int64 pref_sum = 0; // Σ_{k=0}^{K-1} C(N,k) int64 cur = 1; // C(N,0) for (int k = 0; k < K; ++k) { pref_sum += cur; if (pref_sum >= MOD) pref_sum -= MOD; // 次項へ: cur = cur * (N-k)/(k+1) int64 mult = (N - k) % MOD; cur = mul_mod(cur, mul_mod(mult, inv_num(k + 1))); } ans = (two_pow_N - pref_sum) % MOD; if (ans < 0) ans += MOD; } cout << ans << '\n'; return 0; }