#include #include #include #include #include #include using mint = atcoder::modint998244353; template mint count_increasing_sequence_with_upper_bound( const std::vector& upper_bounds) { const auto n = upper_bounds.size(); const auto m = upper_bounds.end()[-1]; std::vector fact(n + m + 1), fact_inv(n + m + 1); { fact[0] = 1; const auto &range = std::views::iota(1) | std::views::take(n + m); for(const auto i : range) { fact[i] = i * fact[i - 1]; } fact_inv[n + m] = fact[n + m].inv(); for(const auto i : range | std::views::reverse) { fact_inv[i - 1] = i * fact_inv[i]; } } const auto&& rec = [&](auto&& rec, const int l, const int r, const int d, const std::vector& bottom) { if(l + 1 == r) { return std::vector(upper_bounds[l] - d, l == 0 ? mint::raw(1) : bottom[0]); } const int m = (l + r) / 2; const int h = upper_bounds[m] - d, w = r - m; auto left = rec(rec, l, m, d, std::vector(bottom.begin(), bottom.begin() + m - l)); left.resize(h); std::vector top(w); std::vector right(upper_bounds[r - 1] - d); if(h > 0) { { std::vector f(h), g(h + w); for(const auto i : std::views::iota(0, h)) { f[i] = left[i] * fact_inv[h - 1 - i]; } for(const auto i : std::views::iota(0, h + w)) { g[i] = fact[i]; } f = convolution(f, g); for(const auto i : std::views::iota(0, w)) { top[i] += fact_inv[i] * f[h - 1 + i]; } } { std::vector f(w), g(w); for(const auto i : std::views::iota(0, w)) { f[i] = bottom[i + m - l]; } for(const auto i : std::views::iota(0, w)) { g[i] = fact[h - 1 + i] * fact_inv[i]; } f = convolution(f, g); for(const auto i : std::views::iota(0, w)) { top[i] += fact_inv[h - 1] * f[i]; } } { std::vector f(h), g(h + w); for(const auto i : std::views::iota(0, h)) { f[i] = left[i]; } for(const auto i : std::views::iota(0, h + w)) { g[i] = fact[w - 1 + i] * fact_inv[i]; } f = convolution(f, g); for(const auto i : std::views::iota(0, h)) { right[i] += fact_inv[w - 1] * f[i]; } } { std::vector f(w), g(h + w); for(const auto i : std::views::iota(0, w)) { f[i] = bottom[m - l + i] * fact_inv[w - 1 - i]; } for(const auto i : std::views::iota(0, h + w)) { g[i] = fact[i]; } f = convolution(f, g); for(const auto i : std::views::iota(0, h)) { right[i] += fact_inv[i] * f[w - 1 + i]; } } } else { for(const auto i : std::views::iota(0, w)) { top[i] = bottom[i + m - l]; } } std::vector upper_right = rec(rec, m, r, upper_bounds[m], top); const auto k = upper_right.size(); for(const auto i : std::views::iota(0uz, k)) { right[i + h] += upper_right[i]; } return right; }; const auto right = rec(rec, 0, n, 0, std::vector(n)); return std::accumulate(right.begin(), right.end(), mint(0)); } int main() { std::string s; std::cin >> s; std::vector A = {1}; int val = 1; for(const auto &c : s | std::views::reverse) { if(c == 'A') { ++val; } else { A.push_back(val); } } std::cout << count_increasing_sequence_with_upper_bound(A).val() << '\n'; }